【问题标题】:Count keys within array elements计算数组元素中的键
【发布时间】:2017-08-16 03:32:39
【问题描述】:

您好,我想在 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
        }
    ]
}

【问题讨论】:

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


    【解决方案1】:

    您实际要求的是匹配数组元素中的“键数计数”。根据可用的 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,其中任何测试的数组元素都返回@ 987654337@ 通过$anyElementTrue.

    所有其他版本

    在其他任何地方,使用 $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
            }
        ]
    }
    

    【讨论】:

    • 感谢您的回答,但由于我的 MongodDb 版本是 2.6.12,因此无法正常工作。我尝试了 JavaScript,但出现与符号 &gt; 相关的错误
    • @KristCont 如果你的“shell”真的很古老,那么它不理解 ES6 语法。在较旧的“服务器”版本中使用更现代的 shell 并没有错。但您也可以将$where 参数更改为return this.features.some(function(f) { return Object.keys(f).length &lt; 2 })
    • 我试过你在上面的评论中所说的,但它返回错误`Object.keys called on non-object near 'ys(f).length
    • @KristCont 不是来自您在问题中提供的数据。您收到此类错误的唯一方法是您的实际数据结构与问题中发布的内容不同。我的答案是根据提供的数据运行的。复制并粘贴到集合中,结果复制并粘贴到答案中。我建议你这样做。如果您无法弄清楚如何应用与您实际询问的“不同的数据”,那么您Ask a New Question。但你所问的,已经得到了回答。
    猜你喜欢
    • 2016-05-19
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 2021-10-10
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多