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