MongoDB "find" query with multiple query documents - java

I am using MongoDB 3.2 with Java. I read the documentation and it says to use org.bson.BsonDocument since other options like BSONObject and Document are deprecated. Now, I have query similar to:
db.schools.find({ zipcode: "63109" },
{ students: { $elemMatch: { school: 102 } } } )
I am wondering: how can I write this query in Java?
Note: Here we have two documents inside the find function, while it accepts only single Bson Document or multiple Bson Element(s).
Any help would be appreciated.

Try to use one document for the condition, like db.schools.find({ zipcode: "000000", students: { $elemMatch: { school: 102 }});
EDIT:
So, you are using Projection. In java mongodb driver 3.3 there are: public DBCursor find(DBObject query, DBObject projection). I think you should update your java mongodb driver.

Related

Morphia ignores collation

I have a mongo 3.4 server and I need to run case insensitive queries.
I have created the proper index and I can make case insensitive queries through the mongo console.
db.users.find( {"name": "alex" }, { "name" : 1 } ).collation( { locale: 'en', strength: 2 } )
returns any user that has as name Alex, alex, ALEX etc
I need to do the same from my java program that uses morphia 1.3.1.
Collation col = Collation.builder().locale("en").collationStrength(CollationStrength.SECONDARY).build();
FindOptions fo = new FindOptions().collation(col);
q.disableValidation().asList(fo);
The program retuns only the users that has as name the pecified parameter.
If i set the name as Alex then I will not get the users with name alex, ALEX etc
Is there something extra that I had to do with morphia to make the collation to work?
I have alternate way to solve your problem.
Use regular expression in query.
db.users.find({"name":{$regex:/^alex$/i}})
To do this in java code. Write one java function which will construct string like above e.g.
{"name":{$regex:/^alex$/i}}
And use below code to get DBCursor
public DBCursor find(String jsonString) {
if(StringUtils.trimToNull(jsonString) != null) {
DBObject dbObject = (DBObject)JSON.parse(jsonString);
return collection.find(dbObject);
}
return null;
}
Then get list of DBObject from DBCursor and use morphia.fromDBObject function to get your result in required class.
Another way you can go is Create text index on required fields and search with whatever you want. see details here: https://docs.mongodb.com/manual/reference/operator/query/text/#text-operator-case-sensitivity

Too many parameters error on the following $in query

I'm using jongo API - org.jongo.MongoCollection is the class.
I have list of object ids and converted the same as ObjectId[] and trying to query as follows
collection.find("{_id:{$in:#}}", ids).as(Employee.class);
The query throws the exception - "java.lang.IllegalArgumentException: Too
many parameters passed to query: {"_id":{"$in":#}}"
The query doesn't work as specified in the URL In Jongo, how to find multiple documents from Mongodb by a list of IDs
Any suggestion on how to resolve?
Thanks.
Try it with a List as shown on the docs:
List<String> ages = Lists.newArrayList(22, 63);
friends.find("{age: {$in:#}}", ages); //→ will produce {age: {$in:[22,63]}}
For example the following snippet I crafted quick & dirty right now worked for me (I use older verbose syntax as I am currently on such a system ...)
List<ObjectId> ids = new ArrayList<ObjectId>();
ids.add(new ObjectId("57bc7ec7b8283b457ae4ef01"));
ids.add(new ObjectId("57bc7ec7b8283b457ae4ef02"));
ids.add(new ObjectId("57bc7ec7b8283b457ae4ef03"));
int count = friends.find("{ _id: { $in: # } }", ids).as(Friend.class).count();

How to get array of document using Mongodb java?

How to get all the document under array in mongodb java. My Database is as below. Want to retrieve all the data under array 198_168_1_134.
below is some of What i tried,
eventlist.find(new BasicDBObject("$match","192_168_10_17"))
eventlist.find(new BasicDBObject("$elemMatch","192_168_10_17"))
eventlist.find(null, new BasicDBObject("$192_168_10_17", 1))
You have two options:
using .find() with cherry-picking which document you have to have fetched.
using the aggregation framework by projecting the documents.
By using .find() , you can do:
db.collection.find({}, { 192_168_10_17 : 1 })
By using the aggregation framework, you can do:
db.collection.aggregate( { $project : { 192_168_10_17 : 1 } } )
which will fetch only the 192_168_10_17 document data.
Of course, in order to get this working in Java, you have to translate these queries to a corresponding chain of BasicDBObject instances.
By using mongo java driver you can do this by following query -
eventlist.find(new BasicDBObject(), new BasicDBObject("198_168_1_134", 1))

How to compare 2 fields in Spring Data MongoDB using query object

What seems almost natural in simple SQL is impossible in mongodb.
Given a simple document:
{
"total_units" : 100,
"purchased_unit" : 60
}
I would like to query the collection, using spring data Criteria class, where "total_units > purchased_units".
To my understanding it should be as trivial as any other condition.
Found nothing to support this on Spring api.
You can use the following pattern:
Criteria criteria = new Criteria() {
#Override
public DBObject getCriteriaObject() {
DBObject obj = new BasicDBObject();
obj.put("$where", "this.total_units > this.purchased_units");
return obj;
}
};
Query query = Query.query(criteria);
I don't think Spring Data API supports this yet but you may need to wrap the $where query in your Java native DbObject. Note, your query performance will be fairly compromised since it evaluates Javascript code on every record so combine with indexed queries if you can.
Native Mongodb query:
db.collection.find({ "$where": "this.total_units > this.purchased_units" });
Native Java query:
DBObject obj = new BasicDBObject();
obj.put( "$where", "this.total_units > this.purchased_units");
Some considerations you have to look at when using $where:
Do not use global variables.
$where evaluates JavaScript and cannot take advantage of indexes.
Therefore, query performance improves when you express your query
using the standard MongoDB operators (e.g., $gt, $in). In general, you
should use $where only when you can’t express your query using another
operator. If you must use $where, try to include at least one other
standard query operator to filter the result set. Using $where alone
requires a table scan. Using normal non-$where query statements
provides the following performance advantages:
MongoDB will evaluate non-$where components of query before $where
statements. If the non-$where statements match no documents, MongoDB
will not perform any query evaluation using $where. The non-$where
query statements may use an index.
As far as I know you can't do
query.addCriteria(Criteria.where("total_units").gt("purchased_units"));
but would go with your suggestion to create an additional computed field say computed_units that is the difference between total_units and purchased_units which you can then query as:
Query query = new Query();
query.addCriteria(Criteria.where("computed_units").gt(0));
mongoOperation.find(query, CustomClass.class);
Thanks #Andrew Onischenko for the historic good answer.
On more recent version of spring-data-mongodb (ex. 2.1.9.RELEASE), I had to write the same pattern like below:
import org.bson.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
// (...)
Criteria criteria = new Criteria() {
#Override
public Document getCriteriaObject() {
Document doc = new Document();
doc.put("$where", "this.total_units > this.purchased_units");
return doc;
}
};
Query query = Query.query(criteria);
One way is this:
Criteria c = Criteria.where("total_units").gt("$purchased_unit");
AggregationOperation matchOperation = Aggregation.match(c);
Aggregation aggregation = Aggregation.newAggregation(matchOperation);
mongoTemplate.aggregate(aggregation, "collectionNameInStringOnly", ReturnTypeEntity.class);
Remember to put collection name in string so as to match the spellings of fields mentioned in criteria with fields in database collection.

Exists Query for multilple Document in Mongodb using java driver

If we want to check that the record is exists in Collection or not, then there is an operator $exists in Mongodb. But if we want to know multiple records exists in Collection then how can we check that in single query using java driver?
For Example I have two document:
{"key": "val1"}
{"key": "val2"}
Now if I want to check that 'val1' and 'val2' is exist or not then how can we do that in single query using java driver?
Note: here field name is same in both the documents.
You need to use $in operator for that
db.collection.find( { key : { $in : ['val1','val2'] } } );
equivalent java code might like this
List<string> values = new ArrayList<string>();
values.add("val1")
values.add("val2")
BasicDBObject query = new BasicDBObject();
query.put("key", new BasicDBObject("$in", values));
DBCursor cursor = yourcollection.find(query);
am not much of a java guy, this is going to be more or less same.

Categories

Resources