Criteria/aggregation: 搜索其数组字段包含具有最新给定状态的元素的所有完整文档
Criteria/aggregation: search for all complete documents whose array field has element with latest given status
我有这样的文档结构 -
{
"_id" : "11223344",
"orderId" : "00001041",
"key" : "56h68ab4c876dbe1cd0b1ee"
"status" : [
{
"updatedTimeStamp" : ISODate("2017-06-01T16:05:42.737Z"),
"orderStatus" : "INITIATED"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:05:42.737Z"),
"orderStatus" : "CONFIRM_PAYMENT"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:07:36.797Z"),
"orderStatus" : "RESTAURENT_CONFIRMATION_PENDING"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:20:36.798Z"),
"orderStatus" : "ORDER_CONFIRMED"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:51:27.562Z"),
"orderStatus" : "PREPARED"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T17:31:27.562Z"),
"orderStatus" : "DISPATCHED"
}
],
"customerDetails" : {
"firstName" : "XXXX",
"lastName" : "XXXXX",
"emailId" : "xxxx_xxxx@gmail.com",
"phoneNumber" : "XXXXXXXXX"
},
"amountPaid" : "250.0",
"orderDetails" : {blah... blah... blah...}
}
在此订单集合中,我想搜索给定状态 x(比如 CONFIRM_PAYMENT)的所有文档。所以它是通过文档数组 "status" 中 "updatedTimeStamp" 的最大值找到的,如果最大数组嵌入文档等于状态 "CONFIRM_PAYMENT",那么整个文档应该包含在最终结果中。
我们可以用标准来解决吗API?
有类似的问题 - MongoDB find by max value in array of documents。但我想用 spring 标准或聚合 api 来完成。
以下是我在上述问题的帮助下提出的查询。此查询提供了我想要的文档的所有 ID。我对完整的文件感兴趣。
db.order.aggregate([
{$match: {key:"56h68ab4c876dbe1cd0b1ee"}},
{$unwind: "$status"},
{$project:{Id:"$_id",status:"$status.orderStatus", updatedTimeStamp:"$status.updatedTimeStamp"} },
{$sort:{updatedTimeStamp:1} },
{$group: {_id: "$Id", LatestStatus:{$last: "$status"}, updatedTimeStamp:{$last: "$updatedTimeStamp"} } },
{$match:{"LatestStatus":"CONFIRM_PAYMENT"}},
{$project:{Id:"$Id"}}
])
有人可以用标准或聚合来帮助解决这个问题 API 吗?
*此查询中还有一个过滤器 "key".
您可以使用$expr(3.6 mongo版本运算符)在常规查询中使用聚合函数。
比较query operators
vs aggregation comparison operators
.
使用 $indexOfArray
运算符在状态数组中找到 $max
更新的时间戳元素,然后投影状态值并比较检查值与输入状态。
所以shell查询是
{
"key":"56h68ab4c876dbe1cd0b1ee",
"$expr":{
"$eq":[
{"$let":{
"vars":{
"status":{"$arrayElemAt":["$status",{"$indexOfArray":["$status.updatedTimeStamp",{"$max":"$status.updatedTimeStamp"}]}]}
},
"in":"$$status.orderStatus"
}},
"CONFIRM_PAYMENT"]
}
}
Spring代码:
Query query = new BasicQuery("{key:'56h68ab4c876dbe1cd0b1ee','$expr':{'$eq':[{$let:{vars:{status:{'$arrayElemAt':['$status',{'$indexOfArray':['$status.updatedTimeStamp',{'$max':'$status.updatedTimeStamp'}]}]}}, in:'$$status.orderStatus'}},'CONFIRM_PAYMENT']}}");
List<Document> results = mongoTemplate.find(query, Document.class);
Mongo 3.4投诉版本:
Shell 查询:
db.order.aggregate([
{ "$match" : { "key" : "56h68ab4c876dbe1cd0b1ee"}} ,
{ "$addFields" : {
"cmpret" : {
"$eq" : [
{ "$let" : {
"vars" : { "status" : { "$arrayElemAt" : [ "$status" , { "$indexOfArray" : [ "$status.updatedTimeStamp" , { "$max" : "$status.updatedTimeStamp"}]}]}} ,
"in" : "$$status.orderStatus"
}} ,
"CONFIRM_PAYMENT"
]
}
}} ,
{ "$match" : { "cmpret" : true}} ,
{ "$project" : { "cmpret" : 0}}
])
Spring代码:
AggregationOperation match1 = Aggregation.match(Criteria.where("key").is("56h68ab4c876dbe1cd0b1ee"));
AggregationOperation addFields = new AggregationOperation() {
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
Document cmpret = Document.parse("{'$eq':[{$let:{vars:{status:{'$arrayElemAt':['$status',{'$indexOfArray':['$status.updatedTimeStamp',{'$max':'$status.updatedTimeStamp'}]}]}}, in:'$$status.orderStatus'}},'CONFIRM_PAYMENT']}}");
return new Document("$addFields", new Document("cmpret", cmpret));
}
};
AggregationOperation match2 = Aggregation.match(Criteria.where("cmpret").is(true));
AggregationOperation dropFields = new AggregationOperation() {
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
return new Document("$project", new Document("cmpret", 0));
}
};
Aggregation aggregation = Aggregation.newAggregation(
match1,
addFields,
match2,
dropFields
);
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "order", Document.class);
我有这样的文档结构 -
{
"_id" : "11223344",
"orderId" : "00001041",
"key" : "56h68ab4c876dbe1cd0b1ee"
"status" : [
{
"updatedTimeStamp" : ISODate("2017-06-01T16:05:42.737Z"),
"orderStatus" : "INITIATED"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:05:42.737Z"),
"orderStatus" : "CONFIRM_PAYMENT"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:07:36.797Z"),
"orderStatus" : "RESTAURENT_CONFIRMATION_PENDING"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:20:36.798Z"),
"orderStatus" : "ORDER_CONFIRMED"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T16:51:27.562Z"),
"orderStatus" : "PREPARED"
},
{
"updatedTimeStamp" : ISODate("2017-06-01T17:31:27.562Z"),
"orderStatus" : "DISPATCHED"
}
],
"customerDetails" : {
"firstName" : "XXXX",
"lastName" : "XXXXX",
"emailId" : "xxxx_xxxx@gmail.com",
"phoneNumber" : "XXXXXXXXX"
},
"amountPaid" : "250.0",
"orderDetails" : {blah... blah... blah...}
}
在此订单集合中,我想搜索给定状态 x(比如 CONFIRM_PAYMENT)的所有文档。所以它是通过文档数组 "status" 中 "updatedTimeStamp" 的最大值找到的,如果最大数组嵌入文档等于状态 "CONFIRM_PAYMENT",那么整个文档应该包含在最终结果中。
我们可以用标准来解决吗API?
有类似的问题 - MongoDB find by max value in array of documents。但我想用 spring 标准或聚合 api 来完成。 以下是我在上述问题的帮助下提出的查询。此查询提供了我想要的文档的所有 ID。我对完整的文件感兴趣。
db.order.aggregate([
{$match: {key:"56h68ab4c876dbe1cd0b1ee"}},
{$unwind: "$status"},
{$project:{Id:"$_id",status:"$status.orderStatus", updatedTimeStamp:"$status.updatedTimeStamp"} },
{$sort:{updatedTimeStamp:1} },
{$group: {_id: "$Id", LatestStatus:{$last: "$status"}, updatedTimeStamp:{$last: "$updatedTimeStamp"} } },
{$match:{"LatestStatus":"CONFIRM_PAYMENT"}},
{$project:{Id:"$Id"}}
])
有人可以用标准或聚合来帮助解决这个问题 API 吗? *此查询中还有一个过滤器 "key".
您可以使用$expr(3.6 mongo版本运算符)在常规查询中使用聚合函数。
比较query operators
vs aggregation comparison operators
.
使用 $indexOfArray
运算符在状态数组中找到 $max
更新的时间戳元素,然后投影状态值并比较检查值与输入状态。
所以shell查询是
{
"key":"56h68ab4c876dbe1cd0b1ee",
"$expr":{
"$eq":[
{"$let":{
"vars":{
"status":{"$arrayElemAt":["$status",{"$indexOfArray":["$status.updatedTimeStamp",{"$max":"$status.updatedTimeStamp"}]}]}
},
"in":"$$status.orderStatus"
}},
"CONFIRM_PAYMENT"]
}
}
Spring代码:
Query query = new BasicQuery("{key:'56h68ab4c876dbe1cd0b1ee','$expr':{'$eq':[{$let:{vars:{status:{'$arrayElemAt':['$status',{'$indexOfArray':['$status.updatedTimeStamp',{'$max':'$status.updatedTimeStamp'}]}]}}, in:'$$status.orderStatus'}},'CONFIRM_PAYMENT']}}");
List<Document> results = mongoTemplate.find(query, Document.class);
Mongo 3.4投诉版本:
Shell 查询:
db.order.aggregate([
{ "$match" : { "key" : "56h68ab4c876dbe1cd0b1ee"}} ,
{ "$addFields" : {
"cmpret" : {
"$eq" : [
{ "$let" : {
"vars" : { "status" : { "$arrayElemAt" : [ "$status" , { "$indexOfArray" : [ "$status.updatedTimeStamp" , { "$max" : "$status.updatedTimeStamp"}]}]}} ,
"in" : "$$status.orderStatus"
}} ,
"CONFIRM_PAYMENT"
]
}
}} ,
{ "$match" : { "cmpret" : true}} ,
{ "$project" : { "cmpret" : 0}}
])
Spring代码:
AggregationOperation match1 = Aggregation.match(Criteria.where("key").is("56h68ab4c876dbe1cd0b1ee"));
AggregationOperation addFields = new AggregationOperation() {
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
Document cmpret = Document.parse("{'$eq':[{$let:{vars:{status:{'$arrayElemAt':['$status',{'$indexOfArray':['$status.updatedTimeStamp',{'$max':'$status.updatedTimeStamp'}]}]}}, in:'$$status.orderStatus'}},'CONFIRM_PAYMENT']}}");
return new Document("$addFields", new Document("cmpret", cmpret));
}
};
AggregationOperation match2 = Aggregation.match(Criteria.where("cmpret").is(true));
AggregationOperation dropFields = new AggregationOperation() {
@Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
return new Document("$project", new Document("cmpret", 0));
}
};
Aggregation aggregation = Aggregation.newAggregation(
match1,
addFields,
match2,
dropFields
);
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "order", Document.class);