Criteria/aggregation: search for all complete documents whose array field has element with latest given status

后端 未结 1 1983
礼貌的吻别
礼貌的吻别 2021-01-15 18:53

I have document structure like this -

{
\"_id\" : \"11223344\",
\"orderId\" : \"00001041\",
\"key\" : \"56h68ab4c876dbe1cd0b1ee\"
\"status\" : [
    {
               


        
相关标签:
1条回答
  • 2021-01-15 19:30

    You can use $expr ( 3.6 mongo version operator ) to use aggregation functions in regular query.

    Compare query operators vs aggregation comparison operators.

    Use $indexOfArray operator to find the $max updated timestamp element in status array followed by projecting the status value and comparison to check value against the input status.

    So shell query is

    {
      "key":"56h68ab4c876dbe1cd0b1ee",
      "$expr":{
        "$eq":[
          {"$let":{
            "vars":{
              "status":{"$arrayElemAt":["$status",{"$indexOfArray":["$status.updatedTimeStamp",{"$max":"$status.updatedTimeStamp"}]}]}
            },
            "in":"$$status.orderStatus"
          }},
          "CONFIRM_PAYMENT"]
      }
    }
    

    Spring code:

    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 complaint version:

    Shell Query:

    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 Code:

      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);
    
    0 讨论(0)
提交回复
热议问题