MongoDB: Combine two .find() statements - java

Using Java. I have two .find() queries that I want to combine and get a Document containing the results of both queries. I have managed to create them individually like this. Notice that the queries are on two different top-level fields. The last statement below is a query on the same field with two conditions.
FindIterable<Document> iterable = db.getCollection("1dag").find(new Document("id", "10"));
and
FindIterable<Document> iterable2 = db.getCollection("1dag").find(
new Document().append("timestamp", new Document()
.append("$gte",startTime)
.append("$lte",endTime)));
I can't find any documentation on this.
Is this where I should use the "$and" or "$where" statements?
EDIT is this the way to do it?
FindIterable<Document> iterable7 = db.getCollection("1dag").find(
new Document()
.append("timestamp", new Document()
.append("$gte", startTime)
.append("$lte", endTime))
.append("id", new Document()
.append("$eq", 10)));

Your query will work perfectly.
The query db.inventory.find({id:{$eq:10}})
is equivalent to db.inventory.find({id: 10})
So simplifying your query:
FindIterable<Document> iterable7 = db.getCollection("1dag").find(
new Document().append("timestamp", new Document()
.append("$gte", startTime)
.append("$lte", endTime))
.append("id",10));

To create the equivalent Java query for the following mongo shell query
db.getCollection("1dag").find({
"id": "10",
"timestamp": {
"$gte": 1412204098,
"$lte": 1412204099
}
})
you should specify a logical conjunction (AND) for multiple query conditions by appending conditions to the query document:
FindIterable<Document> iterable = db.getCollection("1dag").find(
new Document("id", "10")
.append("timestamp",
new Document("$gte", 1412204098)
.append("$lte", 1412204099)
)
);

Related

Fetch fields starting with 2 particular substring in mongodb using springboot?

I'm trying to find all the documents with first name starting with Ram or Shyam.
I tried the following which actually worked in mongoDb
db.collection.find({
$or: [
{
name: {
$regex: "^Ram"
}
},
{
"name": {
"$regex": "^Shyam"
}
}
]
})
I got around count of 4k documents with this find.
Now when I tried to convert this mongo shell query into java.
Things do work but only name starting with Shyam get filtered. As a result the count also decreases to 2k.
Can someone please look at the below code and tell me why is it happening?
Why things are working in mongodb and not in java.
Java Equivalent Code --
MongoDatabase database = mongoClient.getDatabase("Friends");
MongoCollection<Document> collection = database.getCollection("Friend");
BasicDBObject filter = new BasicDBObject("$or", Arrays.asList
(new BasicDBObject("name", new BasicDBObject("$regex", "^Ram")).append("name", new
BasicDBObject("$regex", "^Shyam"))));
collection.find(filter).forEach((Consumer<Document>) doc -> {
// some java function
}
I figured out. There is just one some thing as $or operator always take array
In my java code I have converted it into array but just forgot that there is no need to append .
The solution will be --
BasicDBObject filter = new BasicDBObject("$or", Arrays.asList
(new BasicDBObject("name", new BasicDBObject("$regex", "^Ram")),new BasicDbObject("name", new
BasicDBObject("$regex", "^Shyam"))));
collection.find(filter).forEach((Consumer<Document>) doc -> {
// some java function
}
As per your mongo query, you need to match against name field but not on id field. That's the mistake
BasicDBObject filter = new BasicDBObject("$or", Arrays.asList
(new BasicDBObject("name", new BasicDBObject("$regex", "^Ram"))
.append("id", new //Here is the mistake
BasicDBObject("$regex", "^Shyam"))));
It should be
BasicDBObject filter = new BasicDBObject("$or", Arrays.asList
(new BasicDBObject("name", new BasicDBObject("$regex", "^Ram"))
.append("name", new BasicDBObject("$regex", "^Shyam"))));

How to get the updated record count when running the Mongodb aggregation queries With Java driver

I need number of updated MongoDB records in database for the below syntax. Could you anyone help me to get the number of updated records for the below syntax
MongoDatabase database = client.getDatabase("sample);
MongoCollection collection = database.getCollection("collection");
// Created with Studio 3T, the IDE for MongoDB - https://studio3t.com/
Consumer<Document> processBlock = new Consumer<Document>() {
#Override
public void accept(Document document) {
System.out.println(document);
}
};
Consumer<Document> processBlock = new Consumer<Document>() {
#Override
public void accept(Document document) {
System.out.println(document);
}
};
List<? extends Bson> pipeline = Arrays.asList(
new Document()
.append("$match", new Document()
.append("key", "123")
.append("value", "ss")
),
new Document()
.append("$addFields", new Document()
.append("sample", "$_id")
.append("period", period)
)
.append("amount", new Document()
.append("$multiply", Arrays.asList(
"$amountVal",
Decimal128.parse("-1.0")
)
)
)
new Document()
.append("$out", "TMP")
);
collection.aggregate(pipeline)
.allowDiskUse(false)
.forEach(processBlock);
I wrote an article that explains why you should avoid using the Document object as long as you can & transfer the call to MongoDB as a mongo shell script.
Take a look at it. I think that even though you'll have to invest more of your time in learning the mongo shell script in the short run, it will save you huge amount of debugging & performance time in the long run.

How to execute queries with both AND and OR clauses in MongoDB with Java?

I want to execute query in MongoDB 3.2 with Java Driver 3.2, which contains both $and and $or clauses at the same time.
With the reference, I tried the following approach:
List<Document> criteria1 = new ArrayList<>();
List<Document> criteria2 = new ArrayList<>();
criteria1.add(new Document("fetchStatus", new Document("$gte", FetchStatus.PROCESSED_NLP.getID())));
criteria1.add(new Document("fetchStatus", new Document("$lte", fetchStatusParam)));
criteria1.add(new Document("episodeID", new Document("$in", episodeIDs)));
criteria2.add(new Document("fetchStatus", new Document("$eq", PROCESSED_FETCH.getID())));
criteria2.add(new Document("isFullTextRet", new Document("$eq", false)));
BasicDBList or = new BasicDBList();
or.add(criteria1);
or.add(criteria2);
DBObject query = new BasicDBObject("$or", or);
ArrayList<Document> results = dbC_Coll.find(query).into(new ArrayList<>());
Where the criteria1 and criteria2 should be connected with $or while within criteria1 clause the $and should be applied.
The problem is that in MongoDB Java Driver 3.2 there is such no method and I get the Cannot resolve method find(com.mongodb.DBObject) error.
How can I compose a query such as (A && B) || (X && Y) in MongoDB Java Driver 3.2?
Personally, I find it far less confusing to construct the object sequences just like U would with a JSON structure to enhance readability. But it's still just Document() wherever you see {} and List wherever you see []:
Document query = new Document(
"$or", Arrays.asList(
// First document in $or
new Document(
"fetchStatus",
new Document( "$gte", FetchStatus.PROCESSED_NLP.getID() )
.append("$lte", fetchStatusParam)
)
.append("episodeID", new Document( "$in", episodeIDs)),
// Second document in $or
new Document("fetchStatus", PROCESSED_FETCH.getID())
.append("isFullTextRet", false)
)
);
Which is basically the same as:
{
"$or": [
{
"fetchStatus": {
"$gte": FetchStatus.PROCESS_NLP.getID(),
"$lte": fetchStatusParam
},
"episodeID": { "$in": episodeIDs }
},
{
"fetchStatus": PROCESSED_FETCH.getID(),
"isFullTextRet": false
}
]
}
Also there is no need for "explicit" $eq operators, since "equals" is actually the default meaning of a value assignment in a query property anyway.

MongoDB: Query using $gte and $lte in java

I want to perform a query on a field that is greater than or equal to, AND less than or equal to(I'm using java btw). In other words. >= and <=. As I understand, mongoDB has $gte and $lte operators, but I can't find the proper syntax to use it. The field i'm accessing is a top-level field.
I have managed to get this to work:
FindIterable<Document> iterable = db.getCollection("1dag").find(new Document("timestamp", new Document("$gt", 1412204098)));
as well ass...
FindIterable<Document> iterable = db.getCollection("1dag").find(new Document("timestamp", new Document("$lt", 1412204098)));
But how do you combine these with each other?
Currently I'm playing around with a statement like this, but it does not work:
FindIterable<Document> iterable5 = db.getCollection("1dag").find(new Document( "timestamp", new Document("$gte", 1412204098).append("timestamp", new Document("$lte",1412204099))));
Any help?
Basically you require a range query like this:
db.getCollection("1dag").find({
"timestamp": {
"$gte": 1412204098,
"$lte": 1412204099
}
})
Since you need multiple query conditions for this range query, you can can specify a logical conjunction (AND) by appending conditions to the query document using the append() method:
FindIterable<Document> iterable = db.getCollection("1dag").find(
new Document("timestamp", new Document("$gte", 1412204098).append("$lte", 1412204099)));
The constructor new Document(key, value) only gets you a document with one key-value pair. But in this case you need to create a document with more than one. To do this, create an empty document, and then add pairs to it with .append(key, value).
Document timespan = new Document();
timespan.append("$gt", 1412204098);
timespan.append("$lt", 1412204998);
// timespan in JSON:
// { $gt: 1412204098, $lt: 1412204998}
Document condition = new Document("timestamp", timespan);
// condition in JSON:
// { timestamp: { $gt: 1412204098, $lt: 1412204998} }
FindIterable<Document> iterable = db.getCollection("1dag").find(condition);
Or if you really want to do it with a one-liner without temporary variables:
FindIterable<Document> iterable = db.getCollection("1dag").find(
new Document()
.append("timestamp", new Document()
.append("$gt",1412204098)
.append("$lt",1412204998)
)
);

$out in aggregation MongoDB

Can anyone explain me why in Java when i do an aggregation pipeline with "$out" don't write the result in the new collection when i write only this:
Document match = new Document("$match", new Document("top_speed",new Document("$gte",350)));
Document out=new Document("$out", "new_collection");
coll.aggregate(Arrays.asList(
match,out
)
);
When I save the aggregation result and I iterate on it, the new collection is created and the result of the match is inside (Java has an error obviously in this case):
AggregateIterable<Document> resultAgg=
coll.aggregate(Arrays.asList(
match,out
)
);
for (Document doc : resultAgg){
System.out.println("The result of aggregation match:-"+ doc.toJson());
}
I can't understand why.
You can call toCollection() method instead of iterating.
Document match = new Document("$match", new Document("top_speed", new Document("$gte", 350)));
Document out = new Document("$out", "new_collection");
coll.aggregate(Arrays.asList(match, out)).toCollection();

Categories