我要返回的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}
});
答案 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
实际上是在比较数组的“字符串化”表示法,包括括号[]
和间距。这当然是不正确的。