我有一个包含以下对象的Mongo DB:
[
{
"link" : "xxxxx.jpg"
"_id" : ObjectId("5501b1648ef0b4eccc41814e"),
"processed" : {
"320" : true,
"480" : true,
"540" : true,
"720" : true,
"800" : true,
"1080" : true,
"original" : false,
"iPhone" : true
}
}
]
我正在尝试查询任何已处理的值为false的位置,但我似乎无法弄清楚如何查询我不知道哪些键匹配的位置。如果没有循环遍历所有文件,这可能吗?
答案 0 :(得分:2)
使用MongoDB 3.4.4,使用聚合框架查询文档。这可以通过$objectToArray
运算符实现,该运算符允许您将处理字段中的键映射到键/值对数组。该列表很容易过滤,并获得符合您所拥有条件的密钥。
在下面的示例中,聚合管道由一个额外字段组成,该字段保存与上述具有false值的条件匹配的键,因此理想情况下它将是一个数组:
db.collection.aggregate([
{ "$addFields": {
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])
产生
{
"_id" : ObjectId("5501b1648ef0b4eccc41814e"),
"link" : "xxxxx.jpg",
"processed" : {
"320" : true,
"480" : true,
"540" : true,
"720" : true,
"800" : true,
"1080" : true,
"original" : false,
"iPhone" : true
},
"notProcessed" : [
"original"
]
}
从嵌套表达式
开始{
"$filter": {
"input": { "$objectToArray": "$processed" },
"as": "el",
"cond": { "$not": "$$el.v" }
}
}
$filter
运算符{ "$objectToArray": "$processed" }
的输入会将processed
键中的键转换为此数组:
[
{
"k" : "320",
"v" : true
},
{
"k" : "480",
"v" : true
},
{
"k" : "540",
"v" : true
},
{
"k" : "720",
"v" : true
},
{
"k" : "800",
"v" : true
},
{
"k" : "1080",
"v" : true
},
{
"k" : "original",
"v" : false
},
{
"k" : "iPhone",
"v" : true
}
]
和$filter
会将上面的数组过滤为仅包含v
属性为NOT
true
的对象元素:
[
{
"k" : "original",
"v" : false
}
]
然后 $map
将返回一个只有值
[ { "k" : "original", "v" : false } ] => [ "original" ]
所以你最终只有
[ "original" ]
结果。
使用较旧的MongoDB版本,对动态密钥发出查询将非常困难。考虑修改模式以遵循更容易查询的文档模型:
// this operation changes the schema
var processed = [];
db.collection.find().forEach( function(doc) {
for(key in doc.processed) {
if(doc.processed.hasOwnProperty(key)) {
var item = { key: key, value: doc.processed[key] }
processed.push(item);
}
}
doc.processed = processed;
db.collection.save(doc);
});
// modified schema
{
"link": "xxxxx.jpg"
"_id": ObjectId("5501b1648ef0b4eccc41814e"),
"processed": [
{ "key": "320", "value": true },
{ "key": "480", "value": true },
{ "key": "540", "value": true },
{ "key": "720", "value": true },
{ "key": "800", "value": true },
{ "key": "1080", "value": true },
{ "key": "original", "value": false },
{ "key": "iPhone", "value": true }
]
}
您的查询查询只是
db.collection.find({"processed.value": false});
的键
db.collection.aggregate([
{ "$project": {
"link": 1,
"notProcessed": {
"$map" : {
"input": {
"$filter": {
"input": "$processed",
"as": "el",
"cond": { "$not": "$$el.v" }
}
},
"in": "$$this.k"
}
}
} }
])
答案 1 :(得分:0)
使用您在原始帖子中添加的文档架构,我们可以使用Javascript;
processed
对象false
,请将_id
添加到数组_id
对象中具有false
值的processed
查询运行
var arrDoc = [];
db.test.find().forEach(
function anyFalse(doc) {
for(key in doc.processed) {
if(doc.processed.hasOwnProperty(key) && doc.processed[key] === false) {
arrDoc.push(doc._id);
break;
}
}
});
print( arrDoc.join("\r\n") );
示例文档
{
"_id" : ObjectId("5107de525ed6103609000016"),
"link" : "xxxxx.jpg",
"processed" : {
"320" : true,
"480" : true,
"540" : true,
"720" : true,
"800" : true,
"1080" : true,
"original" : false,
"iPhone" : true
}
}
示例输出
ObjectId("5107de525ed6103609000016")
进一步说明
您可以将此javascript函数anyFalse
存储到Mongo中,并在需要时调用它。见store javascript function on server
如评论中所述,您有一个images
数组。此函数将循环遍历所有images
数组,以检查子processed
是否为false。
查询运行
var arrDoc = [];
db.test.find().forEach(
function anyFalse(doc) {
var len = doc.images.length;
for( var i = 0; i < len; i++ ) {
for(key in doc.images[i].processed) {
if(doc.images[i].processed.hasOwnProperty(key) && doc.images[i].processed[key] === false) {
arrDoc.push(doc.images[i]._id);
break;
}
}
}
});
print( arrDoc.join("\r\n") );
示例文档
{
"_id" : ObjectId("5534fe2f3614af9afd23310a"),
"images" : [
{
"_id" : ObjectId("5107de525ed6103609000016"),
"link" : "xxxxx.jpg",
"processed" : {
"320" : true,
"480" : true,
"540" : true,
"720" : true,
"800" : true,
"1080" : true,
"original" : true,
"iPhone" : true
}
},
{
"_id" : ObjectId("5107de525ed6103609000017"),
"link" : "xxxxx.jpg",
"processed" : {
"320" : true,
"480" : true,
"540" : true,
"720" : true,
"800" : true,
"1080" : true,
"original" : false,
"iPhone" : true
}
}
]
}