Spring Data MongoDB AND/OR query with multiple optional parameters - java

I'm trying to execute a query with more than 2 optional parameters but I don't get any result. For the 2 parameters I followed the answer of this question spring-data-mongo - optional query parameters?.
So for example, with the following query everything is ok:
#Query("{$and: [{$or : [ { $where: '?0 == null' } , { a : ?0 } ]}, {$or : [ { $where: '?1 == null' } , { b : ?1 }]}]}")
But if I add one more parameter it stops to work:
#Query("{ $and : [{$and: [{$or : [ { $where: '?0 == null' } , { a : ?0 } ]}, {$or : [ { $where: '?1 == null' } , { b : ?1 }]}]},{$or : [ { $where: '?2 == null' } , { c : ?2 }]}]}")
I triple checked the syntax and seems ok, but I get empty results (even if I'm sure I should obtain at least few documents).
Any idea?

If you try carefully hand-format you query to be more readable, you will note that you have made a few mistakes with the closing brackets.
Try this query instead:
{ $and :
[{
$and:
[
{$or : [ { $where: '?0 == null' } , { a : ?0 }]},
{$or : [ { $where: '?1 == null' } , { b : ?1 }]},
{$or : [ { $where: '?2 == null' } , { c : ?2 }]}
]
}]
}
Side note: I think one $and will be enough, i.e. remove the top-level $and operator.

Related

Mongo DB Query in Arraylist

In my Java Play framework application, I want to store the ArrayList values in mongoDB.
{
"_id" : ObjectId("5832f29bd4c6721e4e8ba4a7"),
"_class" : "com.netas.innovation.entity.Idea",
"title" : "fsaf",
"desc" : "adgg",
"keyWords" : "dgds",
"createdDate" : ISODate("2016-11-21T13:11:55.823Z"),
"checkbox1" : false,
"checkbox2" : false,
"checkbox3" : false,
"scopeOfIdea" : "Herkes",
"template" : false,
"creatorUser" : {
"$ref" : "user",
"$id" : ObjectId("5832f27dd4c6721e4e8ba4a5")
},
"owners" : [
{
"$ref" : "user",
"$id" : ObjectId("5832f27dd4c6721e4e8ba4a5")
}
],
"answer" : {
"$ref" : "answer",
"$id" : ObjectId("5832f29bd4c6721e4e8ba4a6")
},
"fileList" : []
}
i want to search in owners.
My query doesnt work
if(owners != null && !owners.isEmpty()) {
for(int i=0; i<owners.size(); i++) {
criteriaList.add(new **Criteria().elemMatch(Criteria.where("owners.$id").is(owners.get(i).getId())));**
}
}
How can i fix?
i can search by owners.
owners can be two people or three
Thanks for answers
"owners" : [
{
"$ref" : "user(list)",
"$id" : ObjectId("5832ecdb0deb78cc88392c83")
}
$ref : ozgurk,volkany ...
http://prntscr.com/ddz3c9 this example for output... title desc vs vsdate and owners
I'm not a mongodb expert but, I guess you should do somethink like:
List<Criteria> criteriaList = new ArrayList<Criteria>();
...
List idList = new ArrayList();
for (int i = 0; i < owners.size(); i++) {
idList.add(owners.get(i).getId());
}
criteriaList.add(new Criteria().where("owners.$id").in(idList));
...
If you add each owner=owners.get(i).getId() criteria to the list one by one and finally combine all criterias with AND operation you will not get your desired output.
I guess you use Spring data. I tried to write following mongodb query:
db.getCollection('idea').find(
{
"owners.$id": {
"$in" : [
ObjectId("58451c5f13c97bdde9950641"),
ObjectId("28451c5f13c97bdde9950642")
]
}
}
)

Aggregating using Spring mongo group after a project is not finding the correct field

I have a collection with a dataset that looks like:
{
"resource" : "10.10.10.10",
"statistics" : {
"connections" : 17
}
}
{
"resource" : "10.10.10.10",
"statistics" : {
"connections" : 24
}
}
I want to use Mongo's $group/$push mechanism to return a dataset that looks like:
{ "_id" : "10.10.10.10", "statTotals" : [ 17, 24 ] }
In Mongo shell, I can that by doing:
db.testcol.aggregate([ { "$project" : { "resource" : 1 , "total" : "$statistics.connections"}} , { "$group" : { "_id" : "$resource" , "statTotals" : { "$push" : "$total"}}} ])
Now I want to do this using Spring's Mongo data solution in Java. The operations I'm currently trying to use are:
ProjectionOperation projOper = Aggregation.project("resource").and("statistics.connections").as("total");
GroupOperation groupOper = Aggregation.group("resource").push("total").as("statTotals");
Unfortunately, this is generating a pipeline which looks like:
{ "aggregate" : "event" , "pipeline" : [ { "$project" : { "resource" : 1 , "total" : "$statistics.connections"}} , { "$group" : { "_id" : "$resource" , "statTotals" : { "$push" : "$statistics.connections"}}}]}
In the $group, the $push is being done against $statistics.connections instead of $total so the results come back blank.
Any help would be greatly appreciated on this. At first I thought this might be https://jira.spring.io/browse/DATAMONGO-1254 but I've tried using both 1.7.2 as well as 1.8.1 and get the same results.

how to add values in a single field in mongodb

i have a following Document in mongodb
{
"_id" : "1999",
"Email" : "mail#example.com",
"FirstName" : "personFirstNmae",
"LastName" : "personLastName",
"UserStatus" : "INACTIVE",
"FollowingItems" : [
{
"FollowingItemUuid" : "g12345",
"FollowingItemUuidType" : "GALLERY"
}
]
}
i want to achive this
{
"_id" : "1999",
"Email" : "mail#example.com",
"FirstName" : "personFirstNmae",
"LastName" : "personLastName",
"UserStatus" : "INACTIVE",
"FollowingItems" : [
{
"FollowingItemUuid" : "g12345",
"FollowingItemUuidType" : "GALLERY"
},
{
"FollowingItemUuid" : "M121",
"FollowingItemUuidType" : "MUSEUM"
}
]
}
here is my code
val q=QueryBuilder.start("_id").is("1999")
var update=collection.update(q.get,new BasicDBObject("$set",new BasicDBObject("FollowingItems.$.FollowingItemUuid","M121").append("FollowingItems.$.FollowingItemUuidType","MUSEUM")))
but it throws following exception
com.mongodb.WriteConcernException: { "serverUsed" : "Localhost:27017" , "ok" : 1 , "n" : 0 , "updatedExisting" : false , "err" : "cannot use the part (FollowingItems of FollowingItems.FollowingItemUuid) to traverse the element ({FollowingItems: [ { FollowingItemUuid: \"g12345\", FollowingItemUuidType: \"GALLERY\" } ]})" , "code" : 16837}
at com.mongodb.CommandResult.getWriteException(CommandResult.java:90)
at com.mongodb.CommandResult.getException(CommandResult.java:79)
at com.mongodb.DBCollectionImpl.translateBulkWriteException(DBCollectionImpl.java:316)
at com.mongodb.DBCollectionImpl.update(DBCollectionImpl.java:274)
at com.mongodb.casbah.MongoCollectionBase$class.update(MongoCollection.scala:882)
at com.mongodb.casbah.MongoCollection.update(MongoCollection.scala:1162)
Please guide me how can i achive my desried result and what i am doing wrong
You need to use the $push operator to use this. This is the MongoDB shell command:
db.data.update({
"_id": "1999"
}, {
"$push": {
"FollowingItems": {
"FollowingItemUuid": "M121",
"FollowingItemUuidType": "MUSEUM"
}
}
})
And this is your equivalent QueryBuilder syntax:
val q=QueryBuilder.start("_id").is("1999")
var update=collection.update(q.get,new BasicDBObject("$push",new BasicDBObject("FollowingItems.$.FollowingItemUuid","M121").append("FollowingItems.$.FollowingItemUuidType","MUSEUM")))

retrieve values from nested json array in mongodb

My mongo collection has entries in the following format
{
"myobj" : {
"objList" : [
{ "location" : "Texas" },
{ "location" : "Houston"},
{ "name":"Sam" }
]
},
"category" : "cat1"
}
{
"myobj" :
{
"objList" : [
{ "location" : "Tennesy" },
{ "location" : "NY"},
{ "location" : "SF" }
]
},
"category" : "cat2"
}
I want to extract the "**category**" where location is "Houston". In case of simple JSON object I have to just pass it as query like:
BasicDBObject place = new BasicDBObject();
place.put("location", "Houston");
But in case of nested JSON I don't know how to pass it as a query and get the appropriate category. ie If I pass my location as"Houston" then it should return it's appropriate category "cat1"...i hope my question is clear now....
Ok, you have your documents:
db.coll1.insert({
"myobj" : {
"objList" : [
{ "location" : "Texas" },
{ "location" : "Houston"},
{ "name":"Sam" }
]
},
"category" : "cat1"
})
and
db.coll1.insert({
"myobj" : {
"objList" : [
{ "location" : "Tennesy" },
{ "location" : "Houston"},
{ "location" : "SF" }
]
},
"category" : "cat1"
})
Now you can find what you want using the dot operator:
db.coll1.find({"myobj.objList.location": "Texas"}).pretty() will return one object which has Texas
db.coll1.find({"myobj.objList.location": "SF"}).pretty() will return one object which has SF
db.coll1.find({"myobj.objList.location": "Houston"}).pretty() will return both objects
And now I hope you will be able to write it in Java. I have never used Java, but based on this question you can do something like this. If it will not work, just look how to use dot operator in java driver for mongo:
DBCursor cursor = coll1.find(new BasicDBObject("myobj.objList.location", "Texas"));
P.S. you told, that you wanted to retrieve category. In such a way, you will need to use a projection db.coll1.find({<the query I provided}, {category: 1, _id: 0})

com.mongodb.MongoException: invalid operator: $or

I want to run a query, which returns all elements of a collection, in which
the fields wasProposed and markedByUser are true and
the field recipientEmail is either email1#example.com or email2#example.com.
In my Java code, I create a BasicDBObject, whose toString returns this:
{
"wasProposed" : true ,
"recipientEmail" :
{
"$or" :
[
{ "recipientEmail" : "email1#example.com" } ,
{ "recipientEmail" : "email2#example.com" }
]
},
"markedByUser" : true
}
When I run this query (rcoll.find(query).sort(sortclause).limit(ITEMS_TO_SHOW)), I get the error com.mongodb.MongoException: invalid operator: $or.
How can I modify the query above in order to get rid of this error?
It's probably cleaner to use $in here instead of an $or:
{
"wasProposed" : true ,
"recipientEmail" : { "$in" : ["email1#example.com", "email2#example.com"] },
"markedByUser" : true
}

Categories