Spring Data MongoDB Date between two Dates - spring

i'm using Spring Data for MongoDB and got the following classes
class A {
List<B> b;
}
class B {
Date startDate;
Date endDate;
}
when i save an object of A it gets persisted like
{
"_id" : "DQDVDE000VFP8E39",
"b" : [
{
"startDate" : ISODate("2009-10-05T22:00:00Z"),
"endDate" : ISODate("2009-10-29T23:00:00Z")
},
{
"startDate" : ISODate("2009-11-01T23:00:00Z"),
"endDate" : ISODate("2009-12-30T23:00:00Z")
}
]
}
Now i want to query the db for documents matching entries in b where a given date is between startDate and endDate.
Query query = new Query(Criteria.where("b").elemMatch(
Criteria.where("startDate").gte(date)
.and("endDate").lte(date)
);
Which results in the following mongo query:
{
"b": {
"$elemMatch": {
"startDate" : { "$gte" : { "$date" : "2009-11-03T23:00:00.000Z"}},
"endDate" : { "$lte" : { "$date" : "2009-11-03T23:00:00.000Z"}}
}
}
}
but returns no resulting documents. Does anybody know what i'm doing wrong? I don't get it...
Thank you very much in advance!!

If you want to find docs where date is between the startDate and endDate of a b array element then you need to reverse your gte and lte calls:
Query query = new Query(Criteria.where("b").elemMatch(
Criteria.where("startDate").lte(date)
.and("endDate").gte(date)
);

{"created_at":{$gt:ISODate("2013-04-30T00:00:00Z"),$lt:ISODate("2013-04-30T23:59:59Z")}}

Related

how to define a resolver in appsync to get a range of data between a particular dates in graphQL

{
"version": "2018-05-29",
"operation": "Query",
"index": "sportLeague",
"query": {
"expression": "sportIdLeagueId = :sportIdLeagueId and gsSK = :gsSK",
"expressionValues": {
#set( $sportIdLeagueId = $util.dynamodb.toDynamoDBJson("fixture#${ctx.args.input.sportId}#${ctx.args.input.leagueId}") )
":sportIdLeagueId": $sportIdLeagueId,
}
},
"filter" : {
"expression" : "between(#title, :title)",
"expressionNames" : {
"#startDateUtc" : "startDateUtc"
}
"expressionValues" : {
":start" : $util.dynamodb.toDynamoDBJson($ctx.args.input.startDateUtc)
}
}
}
i need a between condition to satisfy the requirement
requirement: get data between two dates i.e start date and end date
You attribute names and values need to match what is in your expression. (:title needs to have a corresponding value in expressionNames and expressionValues)
Also the between operator syntax is BETWEEN :startDateUtc AND :endDateUtc
There is a tutorial for using DynamoDB Query in AppSync:
https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-dynamodb-resolvers.html#setting-up-the-allpostsbyauthor-resolver-ddb-query
DynamoDB expressions:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html

How to search through nested array and retreive only matched elements with mongo and springdata [duplicate]

This question already has answers here:
Find in Double Nested Array MongoDB
(2 answers)
Spring data Match and Filter Nested Array
(1 answer)
Closed 3 years ago.
I'm looking to search into my collection and retreive only element who matched Criteria.
Here is my collection :
{
"_id" : "id",
"name" : "test",
"groupUsers" : [
{
"name" : "blabla",
"toys" : [
{
"createdAt" : ISODate("2019-10-30T12:59:41.409Z"),
},
{
"createdAt" : ISODate("2019-11-30T12:59:10.409Z"),
},
{
"createdAt" : ISODate("2019-12-30T12:59:12.409Z"),
}
],
"createdAt" : ISODate("2019-10-30T12:33:39.036Z")
},
{
"name" : "blabla2",
"toys" : [
{
"createdAt" : ISODate("2019-10-32T12:59:41.409Z"),
},
{
"createdAt" : ISODate("2019-11-30T12:59:56.409Z"),
},
{
"createdAt" : ISODate("2019-12-30T12:59:15.409Z"),
}
],
"createdAt" : ISODate("2019-10-32T12:33:39.036Z")
}
],
}
I want to retreive the whole collection but it depends when the user was added to the group for example, user blabla2 (in the example above) will only get the whole group but with only the two last toys of the first user in the response.
Anyway, I guess it's something really basic but I don't know why I can't figure it out.
What I'm Doing
I'm doing a first query to get the current user and get when he was added in the group (notice that the date gets converted into java Date Util here).
Aggregation groupAgg = newAggregation(match(Criteria.where("_id").is(groupId).and("groupUsers.userId").is(userId)));
GroupUser groupUser = mongoTemplate.aggregate(groupAgg, Group.class, GroupUser.class).getUniqueMappedResult();
In a second query, I want to get the whole document but only with the Criteria that I define before.
MatchOperation matchedGroup = match(new Criteria("_id").is(groupId));
MatchOperation matchedToys = match(
new Criteria("groupUsers.toys.createdAt").gte(groupUser.getCreatedAt()));
Aggregation aggregation = newAggregation(matchedGroup, matchedToys);
AggregationResults<Group> result = mongoTemplate.aggregate(aggregation, Group.class, Group.class);
Group group = result.getUniqueMappedResult();
This query doesn't work, and I'm looking to something like even if there is no match (for example, none toys has been created yet), it still return the group basic response and not null.
Maybe I need to unwind the nested array ?
Any help is appreciate. I'm using spring data.
Try this query
db.testers.aggregate([
{
$addFields:{
"groupUsers":{
$map:{
"input":"$groupUsers",
"as":"doc",
"in":{
$mergeObjects:[
"$$doc",
{
"toys":{
$filter:{
"input":"$$doc. toys",
"as":"sn",
"cond": {
"$and": [
{ "$gte": [ "$$sn.createdAt", ISODate('2015-06-17T10:03:46.000Z') ] },
]
}
}
}
}
]
}
}
}
}
}
]).pretty()

OrOperator in MongoTemplate not returning values?

I am working on Spring MVC with MongoDB.
I have added criteria for some fields with orOperator, Each Fields has value in database, but List returning is Empty.
criteriaQuery.addCriteria(Criteria.where("First_Name").is(docName.trim())
.orOperator(Criteria.where("Middle_Name").is(docName.trim())
.orOperator(Criteria.where("Last_Name").is(docName.trim()))));
Query printing in console is
Query: { "First_Name" : "ESTHER" , "$or" : [ { "Middle_Name" : "ESTHER" , "$or" : [ { "Last_Name" : "ESTHER"}]}]}, Fields: null, Sort: null
I tried the Like query, but that also results the same
criteriaQuery.addCriteria(Criteria.where("First_Name").regex(docName)
.orOperator(Criteria.where("Middle_Name").regex(docName))
.orOperator(Criteria.where("Last_Name").regex(docName)));
Mongo Query
db.doctor_details.find({ "$or" : {"First_Name" : { "$regex" : "ESTHER"} }, "$or" : [ { "Middle_Name" : { "$regex" : "ESTHER"} , "$or" : [ { "Last_Name" : { "$regex" : "ESTHER"}}]}]})
Help me to get the result, I dont know where my code goes wrong. Help is appreciated!
Thanks
As far as I remember in order to use orOperator you should do:
Query query = new Query(new Criteria().orOperator(criteriaV1,criteriaV2));
it is based on this answer

Spring mongodb Find document if a single field matches in a list within a document

I have some data stored as
{
"_id" : ObjectId("abc"),
"_class" : "com.xxx.Team",
"name" : "Team 1",
"members" : [
{"userId" : 1, "email" : "a#x.com" },
{"userId" : 2, "email" : "b#x.com" },
]
}
{
"_id" : ObjectId("xyz"),
"_class" : "com.xxx.Team",
"name" : "Team 2",
"members" : [
{"userId" : 2, "email" : "b#x.com" },
{"userId" : 3, "email" : "c#x.com" }
]
}
I have 2 POJO classes Team (mapped to entire document),TeamMember (mapped to members inside a document).
Now I want to find to which team a specific user belongs to. For example if I search for a#x.com it should return me the document for Team 1. Similarly searching for b#x.com should return both of them as its in both the documents.
As I am very new to spring, not able to find out how to solve this.
Note: I am using MongoTemplate
somthing like this will do
final QueryBuilder queryBuilder = QueryBuilder.start();
//queryBuilder.and("members.email").is("a#x.com") This will work as well. try it out.
queryBuilder.and("members.email").in(Arrays.asList("a#x.com"))
final BasicDBObject projection = new BasicDBObject();
projection.put("fieldRequired", 1);
try (final DBCursor cursor = mongoTemplate.getCollection(collectionName).find(queryBuilder.get(), projection)
.batchSize(this.readBatchSize)) {
while (cursor.hasNext()) {
DBObject next = cursor.next();
........
// read the fields using next.get("field")
.........
}
}
batchsize and projection is not mandatory. Use projection if you don't want to fetch the whole document. You can specify which field in the document you want to fetch in the result.
You can use below code with the MongoTemplate
Query findQuery = new Query();
Criteria findCriteria = Criteria.where("members.email").is("b#x.com");
findQuery.addCriteria(findCriteria);
List<Team> teams = mongoTemplate.find(findQuery, Team.class);

Springdata mongodb aggregation match

After asking question to understand a bit more of the aggregation framework in MongoDB I finally found the way to do aggregation for my need (thanks to a StackExchange user)
So basically here is a document from my collection:
{
"_id" : ObjectId("s4dcsd5s4d6c54s6d"),
"items" : [
{
type : "TYPE_1",
text : "blablabla"
},
{
type : "TYPE_2",
text : "blablabla"
},
{
type : "TYPE_3",
text : "blablabla"
},
{
type : "TYPE_1",
text : "blablabla"
},
{
type : "TYPE_2",
text : "blablabla"
},
{
type : "TYPE_1",
text : "blablabla"
}
]
}
The idea was to be able to filter only some elements of my collections (avoiding Type 2 and 3). In fact I have more than 30 types and 6 are not allowed but for simplicity I made this example.
So the aggregation command in command line is this one:
db.history.aggregate([{
$match: {
_id: ObjectId("s4dcsd5s4d6c54s6d")
}
}, {
$unwind: '$items'
}, {
$match: {
'items.type': { '$nin': [ "TYPE_2" , "TYPE_3"] }
}
},
{ $limit: 10 }
]);
With this I am able to retrieve the 10 elements items of this document which do not match TYPE_2 and TYPE_3
However when I am using spring data there is no output. I looked a bit at the example to build mine but its still not working.
So I did:
Aggregation aggregation = newAggregation(
match(Criteria.where("id").is(myID)),
unwind("items"),
match(Criteria.where("items.type").nin(ignoreditemstype)),
limit(3),
skip(offsetLong)
);
AggregationResults<PersonnalHistory> results = mongAccess.getOperation().aggregate(query,
"items", PersonnalHistory.class);
PersonnalHistory is marked with annotation #Document(collection = "history") and id with the #id annotation
ignoreditemstype is a list containing TYPE_2 and TYPE_3
Here is what I have in the toString method of aggregation:
{
"aggregate" : "__collection__" ,
"pipeline" : [
{ "$match": { "id" : "s4dcsd5s4d6c54s6d"} },
{ "$unwind": "$items"},
{ "$match": { "items.type": { "$nin" : [ "TYPE_2" , "TYPE_3" ] } } },
{ "$limit" : 3},
{ "$skip" : 0 }
]
}
I tried a lot of stuff (to have at least an answer :) ) like removing id or the nin:
aggregation = newAggregation(
unwind("items"),
match(Criteria.where("items.type").nin(ignoreditemstype)),
limit(3),
skip(offsetLong)
);
aggregation = newAggregation(
match(Criteria.where("id").is(myid)),
unwind("items")
);
For information when I do a simple query like:
query.addCriteria(Criteria.where("id").is(myID));
My document is returned. However I have thousands of items. So I just want to have the 15 first (in fact the 15 first are the 15 last added)
Do you maybe see what I am doing wrong?
Yeah looks like you are passing simple String while it is expecting ObjectId
Aggregation aggregation = newAggregation(
match(Criteria.where("_id").is(new ObjectId(myID))),
unwind("items"),
match(Criteria.where("items.type").nin(ignoreditemstype)),
limit(3),
skip(offsetLong)
);
Now the question is why it works with simple query, my answer would be because spring-data driver is not that mature at least not with aggregation pipeline.

Resources