MongoDb过滤数组中最后一个元素的值

时间:2016-08-06 19:48:10

标签: mongodb aggregation-framework

以下查询无效。任何人都可以指出我的错误吗?

我正在尝试过滤Progress数组中最后一项具有给定状态的所有文档 - 例如"完成"。

db.logdata.aggregate(
    [
        { "$match": { "ProcessingInfo.Progress" : { "$exists": true } } },
        { "$redact":
            {
                "$cond": {
                   "if": { "$eq": [ { "$arrayElemAt": [ "$ProcessingInfo.Progress.State", -1 ], "Done" } ] },
                   "then": "$$KEEP",
                   "else": "$$PRUNE"
                }
            }
        }

    ]
)

示例文档(应该匹配 - 因为最后一个State in Progress数组是" InProgress" ):

{ 
    "_id" : ObjectId("578fa85bb29339a1fa6d6109"), 
    "ProcessingInfo" : {
        "DateStarted" : ISODate("2016-08-06T16:55:58.294+0000"), 
        "Attempt" : NumberInt(1), 
        "LastState" : "Failed", 
        "Progress" : [
            {
                "State" : "Failed", 
                "StateDescription" : ""
            }, 
            {
                "State" : "Success", 
                "StateDescription" : ""
            }, 
            {
                "State" : "Done", 
                "StateDescription" : ""
            }, 
            {
                "State" : "InProgress", 
                "StateDescription" : ""
            }
        ]
    }
}

有点"规避"这个问题我在文档根目录中有一个额外的字段" LastState" - 这可能是要走的路(复杂性)?

1 个答案:

答案 0 :(得分:0)

您的查询有一点语法错误:您的$eq应该在$arrayElemAt数组中,而不是在包含State定义的对象中。由于Styvane的建议,以下查询(已优化以过滤掉ProcessInfo.Progress数组中任何位置没有预期[ { "$match": { "ProcessingInfo.Progress.State" : "InProgress" } }, { "$redact": { "$cond": { "if": { "$eq": [ { "$arrayElemAt": [ "$ProcessingInfo.Progress.State", -1 ] }, "InProgress" ] }, "then": "$$KEEP", "else": "$$PRUNE" } } } ] 的文档)应该返回您的示例文档:

constexpr unsigned long encode_(unsigned long in, const char* s)
{
  return *s ? encode_((in << 8) | s[0], s + 1) : in;
}

constexpr unsigned long encode(const char* s)
{
  return encode_(0, s);
}

constexpr unsigned long operator"" _x(const char* s, long unsigned len)
{      
  return encode(s);
}

int main(int argc, char **argv)
{
  auto x = "hello"_x;
  switch (x)
  {
    case "ola"_x:
      break;

    case "hello"_x:
      break;
  }
}