Spring Mongo aggregation query with concatenating two arrays and project the result - mongodb

I have a MongoDB aggregation query, I need the Spring boot mongo aggregation object example for the Following query.
db.case.aggregate([
{ $project: { item: { $concatArrays: [ "$workApproval.partItems", "$warrantyClaims.items.items" ] } } }
,{ $unwind : "$item"}
])
I am stuck on the concatArray portion, I am not sure how to write the above query in Spring Boot Mongo aggregation, any help is appreciated.

Here you are:
List<AggregationOperation> operations = new ArrayList<>();
operations.add(
Aggregation.project()
.and("workApproval.partItems").concatArrays("warrantyClaims.items.items").as("item")
);
operations.add(Aggregation.unwind("item"));
Aggregation aggregation = Aggregation.newAggregation(operations);

Related

MongoDB Aggregation to Spring Boot nested fields "$slice"?

Please see: Mongo Playground for the data and query.
Trying to figure out the equivalent SpringData MongoDB query for:
"idPlusVals": {
"values": {
"$slice": [
"$sa",
0,
4
]
}
}
Have tried the following but could not get the $slice in:
project().and("idPlusCount").nested(fields("totalCount"))
.and("idPlusVals").nested(bind("values", "sa"));

MongoDB $addField and $indexOfArray in Spring Data

I am trying to implement a custom sort with MongoDB and Spring Data according to Asya Kamsky's post:
List<AggregationOperation> operations = new ArrayList<>();
operations.add(Aggregation.addFields().addField("scorrrz")
.withValueOfExpression("{ \"$indexOfArray\" : [ [\"John\", \"Bill\"], \"$name\" ] }").build());
When I try to execute this, I get:
ERROR a.insurance.misc.ErrorAttributes - /api/v1/insurance/opportunity/all
org.springframework.expression.spel.SpelParseException: Expression [{ "$indexOfArray" : [ ["John", "Bill"], "$name" ] }] #29: EL1043E: Unexpected token. Expected 'rsquare(])' but was 'comma(,)'
Is this not the right syntaxt? How can this be done with Spring Data?
Collection<String> nameList = Arrays.asList("John", "Bill");
Aggregation agg = newAggregation(
addFields()
.addField("scorrrz").withValue(arrayOf(nameList).indexOf("$name"))
.build()
);
The aggregation's projection is an $addFields stage with a $indexOfArray aggregation array operation. This will return a field scorrrz, and it will have index value or -1 when there is no match. This ran okay with Spring Boot v2.3.10 and MongoDB v4.2.8.
The run this aggregation pass the pipeline agg to the MongoTemplate#aggregate method.
If you want to calculate $indexOfArray using the array from the DB document itself, you need the aggregate pipeline to perform the calculation instead of the Java code.
Here is my solution
Aggregation.addFields()
.addField("scorrrz")
.withValueOf(MongoExpression.create(" $indexOfArray : [ [ 'John', 'Bill' ], '$name' ]"))
.build()
This creates the following pipeline stage
{
"$addFields": {
"scorrrz": {
"$indexOfArray": [
[
"John",
"Bill"
],
"$name"
]
}
}
}

How to update/insert into a mongodb collection with the result of aggregate query on the another collection

I have a below aggregate query and I wanted to insert/update this result into another collection.
db.coll1.aggregate([
{
$group:
{
_id: "$collId",
name: {$first:"$name"} ,
type: {$first:"$Type"} ,
startDate: {$first:"$startDate"} ,
endDate: {$first:"$endDate"}
}
}
])
I have another collection coll2, which has fields in the above query and some additional fields too.
I may already have the document created in Coll2 matching the _id:collId in the above query. If this Id matches, I want to update the document with the field values of the result and keep the values of other fields in the document.
If the Id does not exists, it should just create a new document in Coll2.
Is there a way to do it in the MongoDB query. I want to implement this in my Spring application.
We can use $merge to do that. It's supported from Mongo v4.2
db.collection.aggregate([
{
$group:{
"_id":"$collId",
"name": {
$first:"$name"
},
"type":{
$first:"$Type"
},
"startDate":{
$first:"$startDate"
},
"endDate":{
$first:"$endDate"
}
}
},
{
$merge:{
"into":"collection2",
"on":"_id",
"whenMatched":"replace",
"whenNotMatched":"insert"
}
}
])

SELECT avg(rate) FROM ratings WHERE sid=1 in MongoDB

How to implement equivalent of this SQL command in MongoDB?
SELECT avg(rate) FROM ratings WHERE sid=1
No need to grouping.
Yes there is aggregation framework in mongodb where you can make a pipeline of stages you want for query.
db.collection.aggregate([
{
$match: {
"sid": 1
}
},
{
$project: avg(rate): {
$avg: "$rate"
}
}
])
As you know in sql query where part is applied first that's why we've place $match pipeline at first. $match in mongodb is somehow equivalent to where i SQL and there is $avg in mongodb which works the same as AVG in SQL
To solve this, use $avg within the $group aggregation pipeline element. Basic pipeline flow:
match on sid=1 (your WHERE clause)
group by sid (there's only one sid to group by at this point, because the others are filtered out via match), and generate an average within the group'd content
Your pipeline would look something like:
db.rates.aggregate(
[
{ $match: {"sid":1}},
{ $group: { _id: "$sid", rateAvg: {$avg: "$rate" } }}
])

How can i query on embedded document using Spring data mongodb?

My document structure looks like
{
"users":[
{
"email":"user#company.com"
"messages":[
{
"id":"1",
"text":"A",
"from":"Jessy",
"isDeleted":"false"
},{
"id":"2",
"text":"B",
"from":"Jessy",
"isDeleted":"false"
},{
"id":"3",
"text":"C",
"from":"Alan",
"isDeleted":"false"
},{
"id":"4",
"text":"D",
"from":"Amy",
"isDeleted":"true"
},{
"id":"5",
"text":"E",
"from":"Amy",
"isDeleted":"false"
}
]
}
]
}
I want to query on sub document using or & and operations.So my query can be as follow.
select all those messages from the users collection having from as "Amy" and text is "E" or some other Criteria.
I have an idea about the Aggregation Framework supported by Spring data
AggregationOperation match =Aggregation.match(Criteria.where("from").is("Amy").and("text").is("E"));
AggregationOperation unwind = Aggregation.unwind("messages");
Aggregation aggregation = Aggregation.newAggregation(match);
AggregationResults<User> result = this.mongoTemplate.aggregate(aggregation, "users", User.class);
But my problem is that i want to dynamically populate the Criteria like Criteria is at clients end he or she can pass any query to the database i gonna parse that query into Criteria. Any help will be appreciated.