查询嵌套数组中的字符串长度

时间:2019-03-04 21:43:55

标签: mongodb mongodb-query

我要返回的json看起来像这样:

{
  "_id" : "id",
  "_class" : "ClassName",
  "key" : [ 
    {
      "_id" : "keyId",
      "array" : [ 
        {
          "arrKey" : "value"
        }
      ]
    }
  ]
}

我要基于key.array.arrKey[0].value.length()进行查询吗?数组应始终只有一个值。

我不确定是否需要查找或汇总并匹配,但是下面是我尝试执行此查询的尝试。

var cursor = db.getCollection('collection').find( {
    key.array.arrKey[0].value.length: {$gt: 5} 
});

1 个答案:

答案 0 :(得分:1)

您可以在$strLenCP中使用$expr并仔细处理数组处理:

db.collection.find({
  "$expr": {
    "$anyElementTrue": {
      "$map": {
        "input": {
          "$reduce": {
            "input": "$key.array.arrKey",
            "initialValue": [],
            "in": { "$concatArrays": [ "$$value", "$$this" ] }
          }
        },
        "in": { "$gte": [ { "$strLenCP": "$$this" }, 5 ] }
      }
    }
  }
})

如果您的MongoDB版本早于3.6,则可以改用$where

db.collection.find({
  "$where": function() {
     return this.key.reduce((o,e) => o.concat(e.array.map(a => a.arrKey)), [])
       .some(e => e.length >= 5);
  }
})

两者都遵循相同的原理,即通过“连接”成单个字符串数组来访问内部数组元素,然后测试这些元素以查看它们是否符合长度要求。


以下是为了阻止错误的响应

注意:在其他任何人跳到这里说“嘿,你不能这样做吗?”

db.collection.find({
  "$expr": { "$gte": [ { "$strLenCP": "$key.array.arrKey" }, 5 ] }
})

然后 不,您不能 ,原因很简单,就是查看聚合表达式符号实际上的作用

db.collection.aggregate([
  { "$project": {
    "value": "$key.array.arrKey"
  }}
])

返回:

{ "_id" : "id", "value" : [ [ "value" ] ] }

因此,"$key.array.arrKey"的返回值不是"value"的“字符串”,而是如上所述的嵌套数组。因此,将 reduce array并置到单个字符串数组,然后对这些数组元素进行 map 操作以测试每个元素

这就是为什么聚合表达式和JavaScript表达式都遵循相同的逻辑模式的原因。由于"$key.array.arrKey"看到的图片与.find({ "key.array.arrKey": { "$exists: true } })可能执行的操作完全不同。

聚合表达式和查询运算符的工作 完全不同

  

当然要注意寻找比6长的字符串(或比实际字符串长的任何长度):

 db.collection.find({
   "$expr": { "$gte": [ { "$strLenCP": "$key.array.arrKey" }, 6 ] }
 })
     

将错误地返回问题中提供的文档。

     

还要注意,在这种情况下,$strLenCP实际上是在比较数组的“字符串化”表示法,包括括号[]和间距。这当然是不正确的。