Project using array fields in MongoDB Java Driver - java

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<>());

Related

mongodb $or in JAVA

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"
}

MongoDB $regex query for "end with" particular char

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);

Java MongoDB queries, inserting 2 '$or' conditions

I am trying to generate a MongoDB query with Java like the following:
{
"$or": [
{
"user": {
"$exists": true
}
},
{
"parent": {
"$exists":true
}
}
],
"working": 1,
"$or": [
{
"car.id": 3846,
"car.mediaType": 1
},
{
"car.matched.id": 3846,
"car.matched.model": 1
}
]
}
But I cannot do it because when the second $or condition is being added, the first one is overwritten.
I need to search with some of the results of each $or, I can't add it in the same $or. The code is:
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
public class Sample {
public function mongoSearch()
{
BasicDBObjectBuilder queryBuidlerType = BasicDBObjectBuilder.start().add("working", 1);
BasicDBObject user = new BasicDBObject("user", new BasicDBObject("$exists", true));
BasicDBObject parent = new BasicDBObject("parent", new BasicDBObject("$exists", true));
BasicDBObject car = new BasicDBObject();
parentMatch.put("car.id", mId);
parentMatch.put("car.model", mModel);
BasicDBObject carMatched = new BasicDBObject();
parentMatch.put("car.matched.id", mId);
parentMatch.put("car.matched.model", mModel);
BasicDBList or1 = new BasicDBList();
or.add(user);
or.add(parent);
BasicDBList or2 = new BasicDBList();
or.add(car);
or.add(carMatched);
queryBuidlerType.add("$or", or1).add("$or", or2);
DBObject queryType = queryBuidlerType.get();
}
}
You should use $and wrapping both $or :
{
"$and": [
{"$or": [
{
"user": {
"$exists": true
}
},
{
"parent": {
"$exists":true
}
}
]},
{"$or": [
{
"car.id": 3846,
"car.mediaType": 1
},
{
"car.matched.id": 3846,
"car.matched.model": 1
}
]}
],
"working": 1
}
And also, I don't know what you're trying to do, but if you want to match "car.id": 3846" AND "car.mediaType": 1 in the same sub-object, consider using `$elemMatch
In Java :
QueryBuilder queryBuidlerType = QueryBuilder.start("working").is(1);
DBObject or1 = QueryBuilder.start().or(QueryBuilder.start("user").exists(true).get(), QueryBuilder.start("parent").exists(true).get()).get();
DBObject or2 = QueryBuilder.start().or(QueryBuilder.start("car.id").is(mId).and("car.model").is("mModel").get(), QueryBuilder.start("car.matched.id").is(mId).and("car.matched.model").is("mModel").get()).get();
queryBuidlerType.and(or1, or2);
DBObject queryType = queryBuidlerType.get();

Java mongodb - find then average

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 );

How to match a document with existing array elements in mongodb using java driver

Hello all i am trying to match a document using mongodb java driver for eg :
{
"fName" : "abc",
"lName" : "456",
"dob" : "00",
"address" : "xyz"
}
with
"nameIdentity" : [
{
"fName" : "abc",
"lName" : "def",
"dob" : "00",
"address" : "xyz"
},
{
"fName" : "123",
"lName" : "456",
"dob" : "00",
"address" : "789"
}
If i found the document then i don't do anything else add the document. My problem here is if my source document contains fname : abc and lname: 456 this is matching fname in the first set of nameIdentity and lname in the second set of identity. I want this to be a one complete match. I have tried something like this
List<Document> nameIdentities = (List<Document>) matchedDocument.get("nameIdentity");
for (int i=0;i<nameIdentities.size();i++)
{
temp.add(nameIdentities.get(0));
quBasicDBObject=new BasicDBObject("$and",temp);
}
iterable = mongoDatabase.getCollection("entity").find(updatedDocumentTypeOne);
if (iterable.first() == null)
{
updateResult = mongoDatabase.getCollection("entity")
.updateOne(
new Document("_id", new ObjectId(objectId)),
new Document("$push", new Document("nameIdentity", nameList.get(0))));
}
any suggestions where am i going wrong?
UPDATE
You may have to use the aggregation framework.
Maybe something like:
List<Bson> filterList = new ArrayList<>();
filterList.add(new BsonDocument().append("nameIdentity.fName", new BsonString("abc") ));
filterList.add(new BsonDocument().append("nameIdentity.lName", new BsonString("456") ));
FindIterable<org.bson.Document> it = collection.find(Filters.and(filterList));

Categories