Spring Data Mongo Aggregation Function with both $trim and $toLower - java

Trying to convert the following mongo query but cant find a solution to trim and toLower using Spring Aggregation queries
db.qabr.aggregate([
{ $match: {name: { "$ne": '' } }},
{ $group: {
_id: { 'name': { input: { $trim: { input: { $toLower : '$name' }}}}, 'qabrNumber': '$qabrNumber', 'qabristaan': '$qabristaan' }, // can be grouped on multiple properties
count: { "$sum": 1 }
}},
{ $match: {
count: { "$gt": 1 } // Duplicates considered as count greater than one
}
}
]
)
If I do the following:
AddFieldsOperation trimAndLowerName = Aggregation.addFields()
.addFieldWithValue("name", StringOperators.Trim.valueOf(
StringOperators.ToLower.lowerValueOf("name")
))
.build();
I keep getting 168 (InvalidPipelineOperator): 'Unrecognized expression '$trim'' on server
However running just trim or just toLower works:
AddFieldsOperation trimName = Aggregation.addFields()
.addFieldWithValue("name", StringOperators.ToLower.lowerValueOf("name"))
.build();

Related

How to create a Java mongodb driver query that is identical to this mongodb update query with arrayfilter

Demo https://mongoplayground.net/p/_RyWWepvpyD.
I found examples to do with spring-mongodb. But unable to find any working way to do this with mongodb driver based code.
Query:
db.collection.update({
pollID: 123
},
{
"$inc": {
"answerAnalytics.$[element].selectCount": 1
}
},
{
"arrayFilters": [
{
"$or": [
{
"element.option": "1"
},
{
"element.option": "2"
}
]
}
],
"multi": true
})
DBCollectionFindAndModifyOptions dbCollectionFindAndModifyOptions = (new DBCollectionFindAndModifyOptions()).returnNew(true).upsert(false).update(incrObj).arrayFilters(arrayFilters);
dbCollection.findAndModify(queryDocument, dbCollectionFindAndModifyOptions);

Finding exact match in MongoDB query where search criteria is applied to the object level in the list

I have a requirement of fetching data from mongodb and being done using Java Spring Reactive Mongodb library. I am using the following code for this:
Criteria criteria = Criteria.where(QUERYFIELD1).in(listOfIds)
.andOperator(Criteria.where(QUERYFIELD2).gte(ChildDate));
Query query = Query.query(criteria).noCursorTimeout();
reactiveMongoTemplate.find(query, Document.class, COLLECTIONNAME);
Where QUERYFIELD1 is "ChildId" and QUERYFIELD2 is a "ChildDate". Following is the structure of my document:
{
"_id": {
"$oid": "6296968fa63757a93e1cd123"
},
"Level1": {
"Level2": [
{
"ChildId": "1234",
"ChildDate": {
"$date": "2021-04-01T04:00:00.000Z"
}
},
{
"ChildId": "5678",
"ChildDate": {
"$date": "2017-05-16T04:00:00.000Z"
}
},
{
"ChildId": "3456",
"ChildDate": {
"$date": "2008-09-16T04:00:00.000Z"
}
},
{
"ChildDate": {
"$date": "2022-06-01T04:00:00.000Z"
},
"ChildId": "7891"
}
]
}
}
I am trying to find a document which should match the criteria within the Objects under Level2. For e.g. if My criteria has ChildId as "3456" and ChildDate as "2022-06-01T04:00:00.000Z" then I should get empty results as ChildId is matching with Object3 and ChildDate is matching with Object4. But when I use below query, I get 1 record as the match:
{ "Level1.Level2.ChildId" : "3456", "Level1.Level2.ChildDate" : { $gt: new Date("2022-01-01T05:00:00.000+00:00")}}
I am trying to achieve this using Spring Reactive MongoDB. Please help.
You can use $elemMatch for finding the documents that their array includes an item which matches the conditions:
db.collection.find({
"Level1.Level2": {
$elemMatch: {
ChildId: "3456",
ChildDate: {$gt: new Date("2008-09-16T05:00:00.000Z")}
}
}
})
See how it works on the playground example

Convert mongoDB query into Spring Data MongoDB java code

I have the following MongoDB query and I dont know how to convert in Spring Data java code, the group and replaceRoot operations.
db.getCollection('operationData').aggregate([
{ $match: type: "OPERATION_CHEAP", amount: {$gte: 1000},
createdAt: {$gte: ISODate("2020-01-24T23:00:00.000Z")}
},
{ $project: { amount: 1, operationId: 1 } },
{ $sort: { amount: -1 } },
{ $group: { _id: '$operationId', g: { $first: {data: '$$ROOT'} }} }, <----
{ $replaceRoot: { newRoot: '$g.data' }}, <------
{ $sort: { amount: 1 } }
])
This is the code for the match operation:
Criteria criterias = new Criteria()
.andOperator(Criteria.where(Operation.AMOUNT)
.gte(minAmount)
.and(Operation.TYPE).is(OperationTypeEnum.CHEAP_OPERATION)
.and("createdAt").gte(startDate).lte(endDate));
MatchOperation matchOperation = Aggregation.match(criterias);
This is the code for the project operation:
ProjectionOperation projectionOperation = Aggregation.project("amount", "operationId");
And this is the Aggregation operation:
Aggregation aggregation = Aggregation.newAggregation(matchOperation, projectionOperation,
sort(direction, "amount"));
AggregationResults<OperationDataVO> aggregate = mongoTemplate.aggregate(aggregation,
COLLECTION, OperationDataVO.class);
I cant find out how to create and integrate the GroupOperation
Try this way:
Aggregation.group("operationId").first("$$ROOT").as("g");
Aggregation.replaceRoot("g");

Equivalent of $objectToArray using Mongodb java driver 3

I am moving a Mongodb query from Javascript to Java. The object format is as follows:
{
"record": {
"unknownName1": {
"count": 5,
"domain": "domain1"
}, {
...
}, {
"unknownNameN": {
"count": 3,
"domain": "domainN"
}
}
}
The Javascript query has the following portion:
[
{
$project: {
record: {
$objectToArray: "$record"
}
}
}, {
$unwind: { "$record"
}, {
$group: {
device: "$record.k"
},
count: {
$sum: "$record.v.count"
},
domain: {
$min: "$record.v.domain"
}
}
]
I have translated the above to use the Mongodb Java Driver 3 api and have the following:
List<Bson> query = Arrays.asList(
project(include("record")),
unwind("$record"),
group(computed("device", "$record.k"),
sum("count", "$record.v.count"),
min("domain", "$record.v.domain"))
);
The issue I am having is I can't seem to find an equivalent to $objectToArray using the Mongodb Java Driver and the subsequent sum and min operations depend on dot operating the k and v values generated from using $objectToArray.
Is there an equivalent way to map an object with unknown key names into the k and v format used by $objectToArray using the Mongodb Java Driver, preferrably version 3+?
Below will do.
project(computed("record", eq("$objectToArray", "$record")))

java mongodb - get array length without downloading all data

I'm using mongodb to store data for my java program and I have a collection with an array field that has a lot of things in it but i want only to get the length, without all the other data.
Now i'm using this to get it:
((UUID[])document.get("customers")).length
How can I make this not to download all the array?
A possible answer is to create an int that counts the pushes and the pulls of the array but it's not the cleanest method.
You are looking for aggregation framework where you can use the $size operator in your pipeline, this counts and returns the total the number of items in an array:
db.collection.aggregate([
{
"$project": {
"_id": 0, "customer_count": { "$size": "$customers" }
}
}
]);
where the Java equivalent:
DBObject projectFields = new BasicDBObject("_id", 0);
projectFields.put("customer_count", new BasicDBObject( "$size", "$customers" ));
DBObject project = new BasicDBObject("$project", projectFields);
AggregationOutput output = db.getCollection("collectionName").aggregate(project);
System.out.println("\n" + output);
You can use MongoDB's Aggregation Framework to get the size of the array. For example, given the following document structure:
> db.macross.findOne()
{
"_id" : "SDF1",
"crew" : [
"Rick",
"Minmay",
"Roy",
"Max",
"Misa",
"Milia"
]
}
get the size of the array
> db.macross.aggregate(
{ $match: { _id: "SDF1" } },
{ $unwind: "$crew" },
{ $group: { _id: "", count: { $sum: 1 } } },
{ $project: { _id: 0, count: 1 } }
)
{ "count" : 6 }
More detailed and interesting examples are available in the docs.

Categories

Resources