Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb Mongo-匹配对象键为变量的位置_Mongodb_Mongodb Query_Aggregation Framework - Fatal编程技术网

Mongodb Mongo-匹配对象键为变量的位置

Mongodb Mongo-匹配对象键为变量的位置,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我有一个具有以下对象的Mongo DB: [ { "link" : "xxxxx.jpg" "_id" : ObjectId("5501b1648ef0b4eccc41814e"), "processed" : { "320" : true, "480" : true, "540" : true, "720" : true,

我有一个具有以下对象的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,但我似乎不知道如何查询我不知道哪个键匹配的地方。这是否可以在不遍历所有文档的情况下实现?

使用MongoDB 3.4.4,使用聚合框架查询文档。这可以通过运算符实现,该运算符允许您将已处理字段中的键映射到键/值对数组。该列表将很容易过滤,并获得与您的任何条件匹配的密钥

在以下示例中,聚合管道由一个额外字段组成,该字段保存与上述具有假值的条件相匹配的键,因此理想情况下它将是一个数组:

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" }
    }
}
操作员的输入将
处理的
键中的键转换为此数组:

[ 
    {
        "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
    }
]
并将过滤上述数组,使其仅包含
v
属性为
而非
true
的对象元素:

[ 
    {
        "k" : "original",
        "v" : false
    }
]
然后将返回仅包含值的映射数组

[ { "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});
或者使用和返回带有
false
值的键,如下所示

db.collection.aggregate([
    { "$project": {
        "link": 1,
        "notProcessed": { 
            "$map" : {
                "input": {
                    "$filter": {
                        "input": "$processed",
                        "as": "el",
                        "cond": { "$not": "$$el.v" }
                    }
                },
                "in": "$$this.k"
            }
        }
    } }
])

有了一个像你在原始文章中提到的文档模式,我们可以使用Javascript来

  • 查找所有记录
  • 循环处理
    对象
  • 如果任何值等于布尔值
    false
    ,请将
    \u id
    添加到数组中
  • 打印
    处理的
    对象中有
    值的
    \u id
要运行的查询

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") );
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("5107de525ed6103609000016"),
    "link" : "xxxxx.jpg",
    "processed" : {
        "320" : true,
        "480" : true,
        "540" : true,
        "720" : true,
        "800" : true,
        "1080" : true,
        "original" : false,
        "iPhone" : true
    }
}
ObjectId("5107de525ed6103609000016")
{
    "_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
            }
        }
    ]
}
示例输出

{
    "_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")
{
    "_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
            }
        }
    ]
}
进一步说明

您可以将此javascript函数
anyFalse
存储到Mongo中,并在需要时调用它。看


编辑 如注释中所述,您有一个
images
数组。此函数将遍历所有
图像
数组,以检查子
处理的
是否为false

要运行的查询

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") );
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") );

如果OP可以更改所有模式,那么这是一个不错的选择。如果OP不能,(是否允许无耻引用?)这看起来不错,但是这里的对象在数组中,您将如何修改代码以考虑这一点?例如,该数组称为图像,包含多个图像对象。我试图将
doc.processed
修改为
doc.images.0.processed
以处理每个文档中的第一个图像,但使用方括号时出错<代码>文档图像[0]。已处理