计算数组元素中的键

时间:2017-08-16 03:32:39

标签: javascript arrays mongodb mongodb-query aggregation-framework

您好我想在mongodb中返回features数组中数组计数小于2的所有集合。我尝试使用$size,但这是不可能的。

我不想得到结果并循环每个features并计算它。我想返回productId 123,因为它在一个特征数组中的计数为1。请以下文件为例:

{
    "productId" : 123.0,
    "features" : [ 
        {
            "a" : true
        }, 
        {
            "a" : true,
            "b" : true
        }
    ]
},
{
    "productId" : 456.0,
    "features" : [ 
        {
            "a" : true,
            "b" : true
        }, 
        {
            "a" : true,
            "b" : true
        }
    ]
}

1 个答案:

答案 0 :(得分:3)

您实际要求的是匹配数组元素中的“键数”。根据可用的MongoDB版本,您有不同的方法。

MongoDB 3.4.4及以上

您可以使用$objectToArray将每个元素强制转换为“数组”本身,代表元素的“键/值”对:

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$anyElementTrue": { 
          "$map": {
            "input": "$features",
            "as": "f",
            "in": {
              "$lt": [
                { "$size": { "$objectToArray": "$$f" } },
                2
              ]
            }
          }
        }
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

您基本上使用$redact提供条件,该条件确定$map的结果,其中$objectToArray应用于每个元素,然后针对$size进行测试,其中任何经过测试的数组元素都通过$anyElementTrue返回true

所有其他版本

在其他任何地方,看起来更简短但实际上并不是性能有效使用$where来应用JavaScript表达式来测试数组元素。使用Object.keys()Array.some()时的原则相同:

db.collection.find({
  "$where": function() {
    return this.features.some(f => Object.keys(f).length < 2 )
  }
})

同样的交易,但由于JavaScript需要对每个文档进行解释和评估,因此它实际上比给定的聚合表达式运行得慢一些。

两者都返回相同的文档,即在内部对象中具有“少于两个键”的元素的文档,就像问的那样:

/* 1 */
{
    "productId" : 123.0,
    "features" : [ 
        {
            "a" : true
        }, 
        {
            "a" : true,
            "b" : true
        }
    ]
}