How to write below mongo query in spring boot - spring

db.abc.find({
"$expr":{
"$and":[
{"$gte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2022-06-10T05:38:56.858Z")]},
{"$lte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2022-06-13T05:07:09.645Z")]}
]
}
})
.projection({})
.sort({_id:-1})
.projection({_id: 0, entityId: 1});
This is the mongo query
i want to convert the object id in timestamp and then compare the dates

Related

Filter by Date with Spring Data MongoTemplate

I would like to filter my filedA's array by dates, with a mongo query it looks like that :
{
$project: {
user: "$$ROOT",
fieldA: {
$filter: {
input: "$fieldA",
as: "a",
cond: {
$and: [
{$lt: ["$$a.constraint", new Date()]},
{$gt: ["$$a.constraint", new Date()]}
]
}
}
}
}
},
The query works but I have trouble when I tried to do it with spring :
project()
.and("$$ROOT").as("user")
.and(
filter("$fieldA")
.as("a")
.by(
and(
ComparisonOperators.Lte.valueOf("a.constraint")
.lessThanEqualTo(dateEnd),
ComparisonOperators.Gte.valueOf("a.constraint")
.greaterThanEqualTo(dateStart)
)
)).as("fieldA"),
I think this is not the right way to make dates comparations but I don't know how to do it properly. Could help me figure out what I'm doing wrong?
try wrapping your dateStart and dateEnd variables in ConvertOperators.ToDate.toDate.
The ComparisonOperators methods (in this case lessThanEqualTo and greaterThanEqualTo) accept either String or AggregationExpression.
By using the ConvertOperators.ToDate.toDate method, you ensure that the passed argument is AggregationExpression and the value is correctly formatted for comparing.
Result would look like this:
import static org.springframework.data.mongodb.core.aggregation.ConvertOperators.ToDate.toDate
...
project()
.and("$$ROOT").as("user")
.and(
filter("$fieldA")
.as("a")
.by(
and(
ComparisonOperators.Lte.valueOf("a.constraint")
.lessThanEqualTo(toDate(dateEnd)),
ComparisonOperators.Gte.valueOf("a.constraint")
.greaterThanEqualTo(toDate(dateStart))
)
)).as("fieldA"),

Spring boot custom query MongoDB

I have this MongoDb query:
db.getCollection('user').find({
$and : [
{"status" : "ACTIVE"},
{"last_modified" : { $lt: new Date(), $gte: new Date(new Date().setDate(new Date().getDate()-1))}},
{"$expr": { "$ne": ["$last_modified", "$time_created"] }}
]
})
It works in Robo3T, but when I put this in spring boot as custom query, it throws error on project start.
#Query("{ $and : [ {'status' : 'ACTIVE'}, {'last_modified' : { $lt: new Date(), $gte: new Date(new Date().setDate(new Date().getDate()-1))}}, {'$expr': { '$ne': ['$last_modified', '$time_created']}}]}")
public List<User> findModifiedUsers();
I tried to make query with Criteria in spring:
Query query = new Query();
Criteria criteria = new Criteria();
criteria.andOperator(Criteria.where("status").is(UserStatus.ACTIVE), Criteria.where("last_modified").lt(new Date()).gt(lastDay), Criteria.where("time_created").ne("last_modified"));
but it doesn't work, it returns me all users like there is no this last criteria not equal last_modified and time_created.
Does anyone know what could be problem?
I think that this feature is not supported yet by Criteria - check this https://jira.spring.io/browse/DATAMONGO-1845 .
One workaround is to pass raw query via mongoTemplate like this:
BasicDBList expr = new BasicDBList();
expr.addAll(Arrays.asList("$last_modified","$time_created"));
BasicDBList and = new BasicDBList();
and.add(new BasicDBObject("status","ACTIVE"));
and.add(new BasicDBObject("last_modified",new BasicDBObject("$lt",new Date()).append("$gte",lastDate)));
and.add(new BasicDBObject("$expr",new BasicDBObject("$ne",expr)));
Document document = new Document("$and",and);
FindIterable<Document> result = mongoTemplate.getCollection("Users").find(document);

Mongo Spring Projection Query

Hi I am trying to get the below mongo query into spring mongo. I've been trying different ways but I am very fusturated right now. Need help!
db.getCollection('rate_review').aggregate([
{$match:{stars:{$exists:true}}},
{$group:{_id:"$store_id",count:{$sum:"$stars"}, maxCount:{$sum:1}}},
{ $project: { _id: 1, rating:
{
$divide: [ "$count",
{
$multiply: [ "$maxCount", 5 ]
}
]
},
"timestamp":{$add:new Date()} } }
])
This is what I have so far,
return mongoTemplate.aggregate(newAggregation(
match(Criteria.where("stars").exists(true)),
group("$storeId").sum("$stars").as("count").sum("$stars").as("maxCount")
).withOptions(newAggregationOptions().allowDiskUse(true).build()), StoreReview.class, Object.class).getMappedResults();
I need help with the Projection piece.

Implement MongoDB aggregation pipeline with $group stage in java spring

I am trying to implement a MongoDB query in java using Spring mongo.
This is the native MongoDB query:
db.ShieldReport.aggregate([
{$match:{"sellerCode":"e1aaf3"}},
{$project:{bucketName:"$bucketName", brandName: "$brandName", createdTime : "$createdTime", sellerCode : "$sellerCode"}},
{$sort:{"createdTime":-1}},
{$group:
{
_id: { sellerCode: "$sellerCode", bucketName: "$bucketName", brandName: "$brandName"},
itemsSold: { $first: { bucketName: "$bucketName", brandName: "$brandName", createdTime : "$createdTime"} }
}
},
{$sort:{"itemsSold.createdTime":-1}},
{$project : { _id : "$_id.sellerCode", bucketName :"$itemsSold.bucketName", brandName : "$itemsSold.brandName"}}
])
In my Spring java version, I have got it this far:
Aggregation agg = newAggregation(
match(Criteria.where("sellerCode").is(filterR‌​equest.getSellerCode‌​())),
Aggregation.project("bucketName")
.andInclude("brandName")
.an‌​dInclude("createdTim‌​e")
.andInclude("sell‌​erCode"),
sort(Sort.Direction.DESC, "createdTime"),
group("sellerCode", "brandName", "bucketName")
);
But the problem is I am not able to create the itemSold field. How do I create that?
You could restructure your pipeline in Spring as follows:
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(Criteria.where("sellerCode").is(filterR‌​equest.getSellerCode‌​())),
Aggregation.sort(Sort.Direction.DESC, "createdTime"),
Aggregation.group("sellerCode", "bucketName", "brandName")
.first("bucketName").as("bucketName")
.first("brandName").as("brandName")
.first("createdTime ").as("createdTime "),
Aggregation.sort(Sort.Direction.DESC, "createdTime"),
Aggregation.project("bucketName", "brandName")
.and("sellerCode").previousOperation()
);
As you can see some of the pipeline stages have been omitted because they are really not necessary. For instance, the $project pipeline before the $group step can be taken off since the $group pipeline operator will apply the accumulators
In the group step, you group the intermediate filtered documents by the three fields and store the other field values in new fields aided by the $first operator.
Sort the intermediate result by the createdTime field reference of the previous group operation.
Finally in the fourth step, select the "bucketName" and "brandName" fields from the previous group operation. Note that "sellerCode" again implicitly references an group-id field.

Conditional update of several fields

I'm new with rethinkdb, I'm trying to write an update query preferred upsert which will set values to several fields if they don't exist or their values is less than the new value I want to set. Below is the way I did it with mongodb
collection.updateOne(new BasicDBObject(BookKeeperEvent.tenantPropertyName, bookKeeper.getTenantId()).append(BookKeeperEvent.timeLayerPropertyName, bookKeeper.getTimeLayer()),
new BasicDBObject("$max", new BasicDBObject(BookKeeperEvent.latestFullDataPropertyName, bookKeeper.getLatestFullData())
.append(BookKeeperEvent.latestRawDataPropertyName, bookKeeper.getLatestRawData())
.append(BookKeeperEvent.latestHealthPropertyName, bookKeeper.getLatestHealth())
.append(BookKeeperEvent.lastUpdatePropertyName, bookKeeper.getLastUpdate())
.append(BookKeeperEvent.firstFullDataPropertyName, bookKeeper.getFirstFullData()))
.append("$setOnInsert", new BasicDBObject(BookKeeperEvent.tenantPropertyName, bookKeeper.getTenantId()).append(BookKeeperEvent.timeLayerPropertyName, bookKeeper.getTimeLayer())),
new UpdateOptions().upsert(true))
This code set tenantId and timeLayer only if they are null, and for the other fields only if they are null or the value is less than the value I set in the query.
Is there a way to do the same thing in rethinkdb? and how?
I think the following query is equivalent to what I did in mongo but it fails.
r.table('book_keeper').filter({tenantId: '123', timeLayer: 4}).coerceTo('array').do(function (matches) {
return r.branch(
matches.isEmpty(),
r.table('book_keeper').insert({tenantId: '123', timeLayer: 4, latestRawData: 100, id: 4}),
r.table('book_keeper').get(4).update(function (doc) {
return r.branch(
doc.not(doc.hasFields('firstFullData')).or(doc('firstFullData').lt(100)),
{firstFullData : 100},
null)
}
))
})
The excption is:
e: Expected 1 argument but found 2 in:
r.table("book_keeper").filter({"tenantId": "123", "timeLayer": 4}).coerceTo("array").do(function(var_193) { return r.branch(var_193.isEmpty(), r.table("book_keeper").insert({"tenantId": "123", "timeLayer": 4, "latestRawData": 100, "id": 4}), r.table("book_keeper").get(4).update(function(var_194) { return r.branch(var_194.not(var_194.hasFields("firstFullData")).or(var_194("firstFullData").lt(100)), {"firstFullData": 100}, null); })); })
How can I fix it?
Thanks,
Daniela

Resources