如何编写一个查询,选择集合中values
中至少有一个键具有正值的所有对象。
例如,它选择了这个:
{
"_id" : "kDi4C9sZpq782kKJf",
"values": {
"a": -1,
"b": -1,
"c": 1234
}
}
和这个
{
"_id" : "kDi4C9sZpq782kKJf",
"values": {
"345jscf": -1,
"6234gdr": 2341,
"485hfls": -1
}
}
但不是
{
"_id" : "kDi4C9sZpq782kKJf",
"values": {
"a134dsd": -1,
"bdgssvs": -1,
"c345scv": -1
}
}
或
{
"_id" : "kDi4C9sZpq782kKJf",
"values": {
}
}
理想情况下,我想要一些东西
db.coll.find("values.*": {$gt: 0})
其中*匹配任何键。
修改 我已经编辑了这些值,以便更好地描述问题。
答案 0 :(得分:1)
您可以尝试这样
db.collection.find({$and:[{"values":{$ne:{}}},{$or:[{"values.a":{$gt:0}},{"values.b":{$gt:0}},{"values.c":{$gt:0}}]}]}).pretty()
在您的文档中,值不是数组,因此您必须检查值文档的单个元素。
希望它会有所帮助
答案 1 :(得分:1)
您可以使用.aggregate()
方法执行此操作:
db.collection.aggregate([
{ "$group": {
"_id": "$_id",
"valA": { "$push": "$values.a" },
"valB": { "$push": "$values.b" },
"valC": { "$push": "$values.c" },
"values": { "$first": "$values" }
}},
{ "$project": {
"values": 1,
"allvalues": { "$setUnion": [ "$valA", "$valB", "$valC" ] }
}},
{ "$redact": { "$cond": [
{ "$anyElementTrue": [
{ "$map": {
"input": "$allvalues",
"as": "av",
"in": { "$cond": [
{ "$gt": [ "$$av", 0 ]},
true,
false
]}
}}
]},
"$$KEEP",
"$$PRUNE"
]}}
])
返回:
{
"_id" : "kDi4C9sZpq782kKJf",
"values" : {
"a" : -1,
"b" : -1,
"c" : 1234
},
"allvalues" : [
1234,
-1
]
}
此查询仍然可以简化$setUnion
运算符与$redact
db.collection.aggregate([
{ "$group": {
"_id": "$_id",
"valA": { "$push": "$values.a" },
"valB": { "$push": "$values.b" },
"valC": { "$push": "$values.c" },
"values": { "$first": "$values" }
}},
{ "$redact": { "$cond": [
{ "$anyElementTrue": [
{ "$map": {
"input": { "$setUnion": [ "$valA", "$valB", "$valC" ] },
"as": "av",
"in": { "$cond": [
{ "$gt": [ "$$av", 0 ]},
true,
false
]}
}}
]},
"$$KEEP",
"$$PRUNE"
]}}
])
如果values
键没有修复,最好的办法是使用“批量”操作更改文档结构,以获得最大效率。
var bulkOp = db.collection.initializeUnorderedBulkOp();
var count = 0;
db.collection.find().forEach(function(doc) {
var values = doc.values;
var anotherValues = [];
for(var key in values) {
if(Object.prototype.hasOwnProperty.call(values, key)) {
anotherValues.push({"name": key, "value": values[key]});
}
}
bulkOp.find({ "_id": doc._id }).updateOne({
"$set": { "values": anotherValues }
});
count++;
if(count % 125 === 0) {
bulkOp.execute();
bulkOp = db.collection.initializeUnorderedBulkOp();
}
})
if(count > 0) { bulkOp.execute(); }
现在您的文档如下所示:
{
"_id" : "kDi5C9sZpq782kKJf",
"values" : [
{
"name" : "a",
"value" : -1
},
{
"name" : "b",
"value" : -1
},
{
"name" : "c",
"value" : 1234
}
]
}
{
"_id" : "kDi4C9sZpq782kKJf",
"values" : [
{
"name" : "345jscf",
"value" : -1
},
{
"name" : "6234gdr",
"value" : 2341
},
{
"name" : "485hfls",
"value" : -1
}
]
}
然后,您可以使用.aggregate()
方法。
db.collection.aggregate([
{ "$redact": {
"$cond": [
{ "$anyElementTrue": [
{ "$map": {
"input": "$values",
"as": "av",
"in": { "$cond": [
{ "$gt": ["$$av.value", 0] },
true,
false
]}
}}
]},
"$$KEEP",
"$$PRUNE"
]
}}
])