I am trying to execute the following query in java but it returns no results at all even though on command line it works fine! they are identical queries but different results!
BasicDBObject m_query = new BasicDBObject();
BasicDBObject cid = new BasicDBObject();
BasicDBList in = new BasicDBList();
in.add("56eea58b013693083806ab92");
cid.append("client_id", new BasicDBObject("$in", in));
BasicDBObject pcid = new BasicDBObject();
pcid.append("parent_client_id", new BasicDBObject("$in", in));
BasicDBList or = new BasicDBList();
or.add(cid);
or.add(pcid);
m_query.append("$or", or);
System.out.println(m_query);
System.out.println(mongoTemplate().getCollection(datatType).count(m_query));
The printed results are:
>{ "$or" : [ { "client_id" : { "$in" : [ "578ac9492c1ae71f2958d2c2"]}} , { "parent_client_id" : { "$in" : [ "578ac9492c1ae71f2958d2c2"]}}]}
> 0
When I execute the following on mongo cmd I get "5" as result for count:
> db.collection.count({$or : [ {client_id: {$in : ["578ac9492c1ae71f2958d2c2"]}}, {parent_client_id: {$in : ["578ac9492c1ae71f2958d2c2"]}} ]})
> {
"client_id": "56eea58b013693083806ab92",
"activity_type": "client",
"geo_tag": {
"type": "Point",
"coordinates": [
35.83278446,
31.97517983
]
},
"cell_phone": "",
"_platform": "web",
"client_status": "lead",
"phone": "",
"name": "client 2",
"comment": "undefined",
"zip_extension": "",
"contact_title": "",
"user": "Representative"
}
Related
I am using MongoDB Java Driver 3.6.3.
I want to create regex query with group by aggregation to retrieve distinct values.
Let's say I have json:
[{
"name": "John Snow",
"category": 1
},
{
"name": "Jason Statham",
"category": 2
},
{
"name": "John Lennon",
"category": 2
},
{
"name": "John Snow",
"category": 3
}]
I want to create query where regex is like "John.*" and group it by name so there would be only one "John Snow"
Expected result is:
[{
"name": "John Snow",
"category": 1
},
{
"name": "John Lennon",
"category": 2
}]
The answer provided by felix is correct, in terms of Mongo Shell commands. The equivalent expression of that command using the MongoDB Java driver is:
MongoClient mongoClient = ...;
MongoCollection<Document> collection = mongoClient.getDatabase("...").getCollection("...");
AggregateIterable<Document> documents = collection.aggregate(Arrays.asList(
// Java equivalent of the $match stage
Aggregates.match(Filters.regex("name", "John")),
// Java equivalent of the $group stage
Aggregates.group("$name", Accumulators.first("category", "$category"))
));
for (Document document : documents) {
System.out.println(document.toJson());
}
The above code will print out:
{ "_id" : "John Lennon", "category" : 2 }
{ "_id" : "John Snow", "category" : 1 }
You can achieve this with a $regex in $match stage, followed by a $group stage:
db.collection.aggregate([{
"$match": {
"name": {
"$regex": "john",
"$options": "i"
}
}
}, {
"$group": {
"_id": "$name",
"category": {
"$first": "$category"
}
}
}])
output:
[
{
"_id": "John Lennon",
"category": 2
},
{
"_id": "John Snow",
"category": 1
}
]
you can try it here: mongoplayground.net/p/evw6DP_574r
You can use Spring Data Mongo
like this
Aggregation agg = Aggregation.newAggregation(
ggregation.match(ctr.orOperator(Criteria.where("name").regex("john", "i")),
Aggregation.group("name", "category")
);
AggregationResults<CatalogNoArray> aggResults = mongoTemp.aggregate(agg, "demo",demo.class);
I have Collection as following. I have query this collection by user.
{
"user": "username",
"sites": {
"site": "abc",
"keywords": [
{
"keyword": "keyword1",
"dailyranks": [
{
"fild1": "value1"
},
{
"fild2": "value2"
},
{
"fild3": "value3"
},
]
},
{
"keyword": "keyword2",
"dailyranks": [
{
"fild1": "value1"
},
{
"fild2": "value2"
},
{
"fild3": "value3"
},
]
},
],
}
}
I want to get the result from the collection as follows, I want to get the last elements of keyword array in the collection
[
{
"keyword" : "keyword1"
"fild2" : "value2",
"fild3" : "value3"
},
{
"keyword" : "keyword2"
"fild2" : "value2",
"fild3" : "value3"
},
]
I have aggregate using $project, but didn't work out. help me to sort this out.
Code used-
BasicDBObject siteObject = new BasicDBObject();
siteObject.append("keywords", "$sites.keywords.keyword");
siteObject.append("lastrank", "$sites.keywords.dailyranks");
BasicDBList aDBList = new BasicDBList();
aaa.add(new BasicDBObject("user", modelLogin.getUSER_NAME()));
ArrayList<BasicDBObject> doc = new ArrayList<>();
doc.add(new BasicDBObject().append("$unwind", "$sites"));
doc.add(new BasicDBObject("$match", aDBList));
doc.add(new BasicDBObject().append("$project", siteObject));
AggregationOutput output = coll.aggregate(doc);
You can try below aggregation.
Use $map to transform the Keywords array.
Within $map, use $arrayElemAt to project the last and second last values from dailyranks and $let operator to hold the result from $arrayAtElem and project the fild value.
db.coll.aggregate({
$project: {
keywords: {
$map: {
input: "$sites.keywords",
as: "result",
in: {
keyword: "$$result.keyword",
fild2: {$let: {vars: {obj: {$arrayElemAt: ["$$result.dailyranks", -2]}},in: "$$obj.fild2"}},
fild3: {$let: {vars: {obj: {$arrayElemAt: ["$$result.dailyranks", -1]}},in: "$$obj.fild3"}}
}
}
}
}
})
Java Equivalent
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("db")
MongoCollection<Document> collection = db.getCollection("collection");
List<Document> results =
collection.aggregate(
Arrays.asList(
Aggregates.match(Filters.eq("user", modelLogin.getUSER_NAME() )),
Aggregates.project(
Projections.fields(
new Document("keywords",
new Document("$map",
new Document("input", "$sites.keywords").
append("as", "result").
append("in",
new Document("keyword","$$result.keyword").
append("fild2",
new Document("$let",
new Document("vars", new Document("obj",
new Document("$arrayElemAt", Arrays.asList("$$result.dailyranks", -2)))).
append("in", "$$obj.fild2" ))).
append("fild3",
new Document("$let",
new Document("vars", new Document("obj",
new Document("$arrayElemAt", Arrays.asList("$$result.dailyranks", -1)))).
append("in", "$$obj.fild3" )))
)
)
)))
)).into(new ArrayList<>());
I am not able to remove object from an array named Matrix for a Key match
BasicDBObject where = new BasicDBObject();
where.put("INSTITUTION_ID", instid);
where.put("RuleID", ruleid);
BasicDBObject obj1 = new BasicDBObject();
obj1.put("Matrix.Key",new BasicDBObject("$regex","/"+json.getString("Code")+"$/"));
collection.update(where,new BasicDBObject("$pull", obj1));
The code above is not removing object from array. The structure of the array can be found below
"Matrix" : [
{
"Key" : "6M",
"value" : "Queue"
},
{
"Key" : "6N",
"value" : "Queue"
},
{
"Key" : "6O",
"value" : "Queue"
}]
Command-line client
I suggest that before writing queries in Java notation, you first test them in the mongo console, with the regular JavaScript syntax. The following query works for me.
Data
db.matrix.insert(
{
INSTITUTION_ID: 1,
RuleID: 2,
Matrix: [
{
"Key": "6M",
"value": "Queue"
},
{
"Key": "6N",
"value": "Queue"
},
{
"Key": "6O",
"value": "Queue"
}
]
})
Query
db.matrix.update(
{
INSTITUTION_ID: 1,
RuleID: 2,
},
{
$pull:
{
Matrix:
{
Key:
{
$regex: /M$/
}
}
}
})
Data after the update
{
"INSTITUTION_ID" : 1.0000000000000000,
"RuleID" : 2.0000000000000000,
"Matrix" : [
{
"Key" : "6N",
"value" : "Queue"
},
{
"Key" : "6O",
"value" : "Queue"
}
]
}
Java
I am not sure how this update query should be represented in Java, but try this:
BasicDBObject where =
new BasicDBObject()
.put("INSTITUTION_ID", instid);
.put("RuleID", ruleid);
BasicDBObject update =
new BasicDBObject("$pull",
new BasicDBObject("Matrix",
new BasicDBObject("Key",
new BasicDBObject("$regex",
java.util.regex.Pattern.compile(json.getString("Code") + "$")))));
collection.update(where, update);
Okey, let's start. Imagine that we have the next mongo collection:
{
"city": "TWENTYNINE PALMS",
"loc": [-116.06041, 34.237969],
"pop": 11412,
"state": "CA",
"_id": "92278"
}
{
"city": "NEW CUYAMA",
"loc": [-74.823806, 34.996709],
"pop": 80,
"state": "CA",
"_id": "93254"
}
{
"city": "WATERBURY",
"loc": [-72.996268, 41.550328],
"pop": 25128,
"state": "CT",
"_id": "06705"
}
Notice that loc array is [latitude,longitude]
I would like to obtain using java mongo driver the "pop" average of the cities that have the altitude beetwen -75,-70.
So, using SQL I know that the query is:
SELECT avg(pop)
WHERE loc.altitude > -75 AND lloc.altitude < -70
I am very noob in mongodb, this is my current code:
BasicDBObject doc = new BasicDBObject("loc.0", new BasicDBObject("$gte",
-75).append("$lte", -70));
DBCursor cursor = collection.find(doc);
The previous code returns me all the documents that altitude are beetwen (-75,-70), but I do not know how to obtain the average,using mongo driver, I know that I can iterate over results using java..
Thank you
Use the aggregation framework with following aggregation pipeline (Mongo shell implementation):
db.collection.aggregate([
{
"$match": {
"loc.0": { "$gte": -75 },
"loc.1": { "$lte": 70 }
}
},
{
"$group": {
"_id": 0,
"average": {
"$avg": "$pop"
}
}
}
])
With the example above, this outputs to console:
/* 1 */
{
"result" : [
{
"_id" : 0,
"average" : 12604
}
],
"ok" : 1
}
With Java, this can be implemented as follows:
DBObject match = new BasicDBObject();
match.put("loc.0", new BasicDBObject("$gte", -75));
match.put("loc.1", new BasicDBObject("$lte", 70));
DBObject groupFields = new BasicDBObject( "_id", 0);
groupFields.put("average", new BasicDBObject( "$avg", "$pop"));
DBObject group = new BasicDBObject("$group", groupFields);
AggregationOutput output = collection.aggregate( match, group );
I have the following database structure in MongoDB (see below) and I want to do a search query on the fields 'name'
Database structure:
{
"_id" : ObjectId("505ad9a7ed5022cbe1f3dc2e"),
"id" : "10",
"description" : "",
"members" : [{
"id" : "1",
"name" : "Jack"
}, {
"id" : "2",
"name" : "Mike"
}, {
"id" : "3",
"name" : "Laura"
}, {
"id" : "4",
"name" : "Sara"
}, {
"id" : "240",
"name" : "Ronald"
}],
"status" : "active"
},
{
"_id" : ObjectId("5059c214707747cbc5819f6f"),
"id" : "12",
"description" : "",
"members" : [{
"id" : "19",
"name" : "Geoff"
}, {
"id" : "21",
"name" : "Andrew"
}, {
"id" : "23",
"name" : "Rachel"
}, {
"id" : "25",
"name" : "Susan"
}],
"status" : "active"
},
I have the following code will do a search on the field 'description' or 'status'. DBCollection collection = database.getCollection("members");
BasicDBObject or1 = new BasicDBObject();
or1.put("description", Pattern.compile(keyword, Pattern.CASE_INSENSITIVE));
BasicDBObject or2 = new BasicDBObject();
or2.put("status", Pattern.compile(keyword, Pattern.CASE_INSENSITIVE));
BasicDBList or = new BasicDBList();
or.add(or1);
or.add(or2);
BasicDBObject query = new BasicDBObject();
query.put("$or", or);
BasicDBObject select = new BasicDBObject();
select.put("description", 1);
select.put("status", 1);
DBCollection collection = collection.find(query, select);
Question is, how would I do an OR search on the field 'members.name' ? So if I would search for the name or text 'Laura' that the document/record with id 10 will be in the result set.
Would I have to loop through all the results or something like that?
Thanks for any help or suggestions!
If I understand the question correctly, it is really a question about how to search a single field inside of an array. Use the full path to the field in question. In this case, it is "members.name".
Now, if you want to AND the members names together to find records that contain two specific members, just put the individual queries into a BasicDBList as you did with OR and then AND them together. If you want to include the other OR query list, just toss that query object (used in the code sample above) into that BasicDBList to be included with the AND.