How to read nested array from MonogDB using Java - java

I need to find the record/count where eventDetails.eventDelivery.stateCode = "Y-FINISH". It could be in any element in the array list.
Just want to find where stateCode = "Y-FINISH" present in the array list.
Sample Data #1:
{
"_id" : ObjectId("5a2fb09736cf07f6a1146691"),
"activityID" : "",
"eventDetails" : [
{
"eventDelivery" : {
"digital" : {
"secureid" : "1231321212"
},
"stateCode" : "X-FINISH",
"state" : "SUCCESS"
},
{
"eventDelivery" : {
"digital" : {
"secureid" : "8762871121"
},
"stateCode" : "Y-FINISH",
"state" : "SUCCESS"
}
],
}
Sample Data #2:
{
"_id" : ObjectId("5a2fb09736cf07f6a1146691"),
"activityID" : "",
"eventDetails" : [
{
"eventDelivery" : {
"digital" : {
"secureid" : "1231321212"
},
"stateCode" : "X-FINISH",
"state" : "SUCCESS"
},
{
"eventDelivery" : {
"digital" : {
"secureid" : "8762871121"
},
"stateCode" : "Y-FINISH",
"state" : "SUCCESS"
},
{
"eventDelivery" : {
"digital" : {
"secureid" : "7651327152
},
"stateCode" : "Z-FINISH",
"state" : "SUCCESS"
}
],
}
Need to read this using Java.

Using a 3.x version of the Mongo Java driver ...
MongoClient mongoClient = ...;
MongoCollection<Document> collection = mongoClient.getDatabase("...")
.getCollection("...");
Bson filter = Filters.eq("eventDetails.stateCode", "Y-FINISH");
long count = collection.count(filter);

Related

Mongo upsert do not return modified object _id on update

Mongodb 4.2.15
I'm tring to use mongo Updates with Aggregation Pipeline
My request is very big but here it's core structure
db.runCommand({
"update": "collectionName",
"updates": [
{
"q": { ... },
"u": [
{
"$project": { ... },
"$set": { ... },
"$set": { ... },
"$project": { ... }
}
],
"multi": false,
"upsert": true
}
]
});
After the first execute I receive a result with newly created object's _id
{
"n" : 1,
"nModified" : 0,
"upserted" : [
{
"index" : 0,
"_id" : ObjectId("619997f11501d6eb40c6f64a")
}
],
"opTime" : {
"ts" : Timestamp(1637455857, 61),
"t" : NumberLong(5)
},
"electionId" : ObjectId("7fffffff0000000000000005"),
"ok" : 1.0,
"$clusterTime" : {
"clusterTime" : Timestamp(1637455857, 61),
"signature" : {
"hash" : { "$binary" : "hA0tf5DXMqTNmnVXdMVnpnAKCU0=", "$type" : "00" },
"keyId" : NumberLong(7018546168816730116)
}
},
"operationTime" : Timestamp(1637455857, 61)
}
After the second execution of the same request there is no modified object's _id
{
"n" : 1,
"nModified" : 1,
"opTime" : {
"ts" : Timestamp(1637456057, 19),
"t" : NumberLong(5)
},
"electionId" : ObjectId("7fffffff0000000000000005"),
"ok" : 1.0,
"$clusterTime" : {
"clusterTime" : Timestamp(1637456057, 19),
"signature" : {
"hash" : { "$binary" : "U2yCP6nXUrjBN9ZiLanyl0rgxww=", "$type" : "00" },
"keyId" : NumberLong(7018546168816730116)
}
},
"operationTime" : Timestamp(1637456057, 19)
}
The thing is that my filter conditions do not contain _id of the object but I need to return it with response. I see no useful request configurations. Any suggestions is it possible to get _id at response on update case?

How to get a String inside an Object Array using MongoDB Java?

I'm trying to learn MongoDB and I want to get a String inside an Object Array, my MongoDB document is here:
{
"_id" : ObjectId("5f1507fed91e81246c409a59"),
"identification" : "punishment",
"lastID" : 2,
"punishmentsTypes" : [
{
"category" : "OFENSA_JOGADOR",
"reason" : "Ofensa a Jogador",
"group" : [
"HELPER",
"MODERATOR",
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Ofender algum jogador",
"cases" : [
{
"1" : {
"type" : "MUTE",
"duration" : 604800000
}
},
{
"2" : {
"type" : "BAN",
"duration" : 0
}
}
]
},
{
"category" : "FALSIFICACAO",
"reason" : "Falsificação de provas",
"group" : [
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Falsicar provas ao denunciar um jogador em nosso fórum",
"cases" : [
{
"1" : {
"type" : "BAN",
"duration" : 0
}
}
]
},
{
"category" : "HACK",
"reason" : "Hack",
"group" : [
"MODERATOR",
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Uso de cheats ou programas ilícitos",
"cases" : [
{
"1" : {
"type" : "BAN",
"duration" : 7776000000.0
}
},
{
"2" : {
"type" : "BAN",
"duration" : 0
}
}
]
}
],
"unpunishmentTypes" : [
{}
]
}
I've tried this:
MongoCollection<Document> collection = mongoDatabase.getCollection("settings");
BasicDBObject query = new BasicDBObject();
BasicDBObject field = new BasicDBObject();
query.put("id", "punish");
field.put("punishmentsTypes", 1);
field.put("_id", 0);
Document test = collection.find(query).projection(field).first();
assert test != null;
Object object = test.get("punishmentsTypes");
System.out.println(object);
And that's the output:
[Document{{category=OFENSA_JOGADOR}},
Document{{category=FALSIFICACAO}}, Document{{category=HACK}}]
How can I get only the category string, to the output be: OFENSA_JOGADOR, FALSIFICACAO, HACK?
I'm not sure how did you get that result with your query but here is how I get your result:
MongoCollection<Document> collection = mongoDatabase.getCollection("settings");
Document query = new Document();
query.put("identification", "punishment");
Document test = collection.find(query).first();
List<Document> punishmentsTypes = test.getList("punishmentsTypes", Document.class);
for (Document document : punishmentsTypes) {
String category = document.getString("category");
System.out.println(category);
}

Removing default fields from java elasticsearch querybuilder

Elasticsearch Java client's QueryBuider instance is adding properties like
1) order
2) min_doc_count
3) shard_min_doc_count
4) show_term_doc_count_error
5) lang
6) gap_policy
to the final Json query. My query works as expected without those properties. I want to prevent those properties from being added to my final query.
Java:
FilterAggregationBuilder aggregation = AggregationBuilders.filter("id", QueryBuilders.termsQuery("id",
"my-name"));
TermsAggregationBuilder lev1Agg = AggregationBuilders.terms("id").field("id");
lev1Agg.size(1);
lev1Agg.subAggregation(AggregationBuilders.sum("familyMemberCount").field("membersInFamily"));
lev1Agg.subAggregation(AggregationBuilders.sum("totalKidsInFamily").field("kidsInFamily"));
Map<String, String> bucketsPathsMap = new HashMap<>();
bucketsPathsMap.put("familyMemberCount", "familyMemberCount");
bucketsPathsMap.put("totalKidsInFamily", "totalKidsInFamily");
Script script = new Script("params.familyMemberCount / params.totalKidsInFamily");
BucketScriptPipelineAggregationBuilder bs = PipelineAggregatorBuilders
.bucketScript("myScript", bucketsPathsMap, script);
lev1Agg.subAggregation(bs);
aggregation.subAggregation(lev1Agg);
searchSourceBuilder = new SearchSourceBuilder().aggregation(aggregation);
searchSourceBuilder.size(0);
Query built by above code
GET my-alias/_search
{
"size" : 0,
"aggregations" : {
"id" : {
"filter" : {
"terms" : {
"name" : [
"my-name"
],
"boost" : 1.0
}
},
"aggregations" : {
"id" : {
"terms" : {
"field" : "name",
"size" : 1,
"min_doc_count" : 1,
"shard_min_doc_count" : 0,
"show_term_doc_count_error" : false,
"order" : [
{
"_count" : "desc"
},
{
"_term" : "asc"
}
]
},
"aggregations" : {
"familyMemberCount" : {
"sum" : {
"field" : "membersInFamily"
}
},
"totalKidsInFamily" : {
"sum" : {
"field" : "kidsInFamily"
}
},
"myScript" : {
"bucket_script" : {
"buckets_path" : {
"familyMemberCount" : "familyMemberCount",
"totalKidsInFamily" : "totalKidsInFamily"
},
"script" : {
"source" : "params.familyMemberCount / params.totalKidsInFamily",
"lang" : "painless"
},
"gap_policy" : "skip"
}
}
}
}
}
}
}
}

How to count number of occurence of specific field in a collection in Mongodb

I have my collection as shown below:
{
"_id" : NumberLong(366),
"file" : "xyz",
"clist" : {
"account" : "BFS",
"subAccount":"a"
},
},
{
"_id" : NumberLong(366),
"file" : "xyz",
"clist" : {
"account" : "BFS",
"subAccount":"b"
},
},
{
"_id" : NumberLong(366),
"file" : "xyz",
"clist" : {
"account" : "HC",
"subAccount":"c"
},
}
In that I have to group by account and count number of subAccount; for example:
{
account : "BFS",
subAccount : "b",
count : 1,
subAccount :"a",
count : 1
}
If for account BFS, subAccount b exists two times, then I should get output like this:
{
account : "BFS",
subAccount : "b",
count : 2,
subAccount : "a",
count : 1
}
May this help you...
db.coll.aggregate([ {
"$group" : {
"_id" : {
"account" : "$clist.account",
"subAccount" : "$clist.subAccount"
},
"count" : {
"$sum" : 1
}
}
}, {
$project : {
_id : 0,
"account" : "$_id.account",
"subAccount" : "$_id.subAccount",
"count" : "$count"
}
}, {
$group : {
_id : "$account",
"subaccounts" : {
"$push" : {
"subAccount" : "$subAccount",
"count" : "$count"
}
}
}
} ])

How to use MongoDB $let with Spring-Data?

I have a MongoDB collection of places. A typical place has most of the following fields:
{
"_id" : ObjectId("575014dc6b028f07bef53681"),
"_class" : "domain.model.PlaceV1",
"name" : "Γιασεμί",
"primary_photo_url" : "https://irs0.4sqi.net/img/general/original/34666238_STHSh6CHiC7hpAuB4rztRVg6cFc5ylfi15aRaR7zUuQ.jpg",
"seenDetails" : NumberLong(0),
"foursquare_checkins" : 646,
"foursquare_tips" : 28,
"keywords" : [
""
],
"verified" : 1,
"location" : {
"loc" : {
"type" : "Point",
"coordinates" : [
25.898318,
36.831486
]
},
"formattedAddress" : "Χώρα",
"locality" : "Amorgos",
"first_neighbourhood" : "Katapola",
"greek_locality" : "Αμοργός",
"greek_first_neighbourhood" : "Κατάπολα"
},
"contact" : {
"phone_numbers" : [
"+30 2285 074017"
]
},
"price" : {
"priceVotes" : NumberLong(0),
"price" : 0,
"priceVotesSum" : NumberLong(0)
},
"rating" : {
"rating" : 8,
"ratingVotes" : NumberLong(0),
"ratingVotesSum" : NumberLong(0)
},
"categories" : [
{
"cat_id" : NumberLong(10310061000),
"category" : "Café",
"greek_category" : "Καφετέρια",
"weight" : 4
},
{
"cat_id" : NumberLong(11610021000),
"category" : "Bar",
"greek_category" : "Μπαρ",
"weight" : 4
}
]
}
I want to make queries where the sorting will be based on a score that is a result of some expressions and conditions. From the mongo shell I have tried this:
db.place.aggregate([
{$match:{"location.locality":"Athens"}},
{$project:
{name:1, location:1, score:{
$let: {
vars:{ foursquare: {
$cond: { if: { $gte: [ "$foursquare_checkins", 500 ] }, then: 500, else: "$foursquare_checkins" }
},
rating: {$multiply:["$rating.rating", 100]},
},
in:{$add:["$$foursquare", "$$rating", "$seenDetails"]}
}
}
}
},
{$sort: {score: -1}}]).pretty();
This is a simple example of my queries. The score will contain more complex expressions like the distance from a location. The problem is that I cannot find a way to use the $let and the $cond operator in my Java code with Spring. Could anybody help?
You should be able to do this using nested DBObject and a Custom Aggregation Operation.
For Example:
Map operations = new HashMap();
operations.put("name", 1);
operations.put("location", 1);
operations.put("score", new BasicDBObject("$let", new BasicDBObject("vars", new BasicDBObject())));
Then you can create a CustomAggregationOperation to add this to your project
CustomAggregationOperation project = new CustomAggregationOperation(new BasicDBObject("$project", operation));
This will give you the following pipeline:
{ "$project" : { "score" : { "$let" : { "vars" : { }}} , "name" : 1 , "location" : 1}}
Then you can add your other stages:
Aggregation aggregate = Aggregation.newAggregation(match, project, sort);
public class CustomAggregationOperation implements AggregationOperation {
private DBObject operation;
public CustomAggregationOperation (DBObject operation) {
this.operation = operation;
}
#Override
public DBObject toDBObject(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}

Categories

Resources