【问题标题】:MongoDB Query to find from dynamic fieldsMongoDB查询从动态字段中查找
【发布时间】:2016-10-22 19:16:44
【问题描述】:

我在从集合中查找和获取数据时遇到问题。这是我的收藏数据

/* 1 */
{
    "_id" : 1,
    "name" : "sue",
    "age" : 19,
    "type" : 1,
    "points" : {
        "A" : {
            "type" : "label",
            "values" : "abc"
        },
        "B" : {
            "mandatory" : false,
            "type" : "text"
        },
        "C" : {
            "mandatory" : false,
            "type" : "text"
        }
    }
}

/* 2 */
{
    "_id" : 2,
    "name" : "bob",
    "age" : 42,
    "type" : 1,
    "points" : {
        "B" : {
            "type" : "label",
            "values" : ""
        },
        "C" : {
            "mandatory" : false,
            "type" : "text"
        }
    }
}

/* 3 */
{
    "_id" : 3,
    "name" : "ahn",
    "age" : 22,
    "type" : 2,
    "points" : {
        "A" : {
            "type" : "label",
            "values" : "abc"
        },
        "C" : {
            "mandatory" : false,
            "type" : "text"
        }
    }
}

/* 4 */
{
    "_id" : 4,
    "name" : "xi",
    "age" : 34,
    "type" : 2,
    "points" : {
        "A" : {
            "type" : "label",
            "allowedValues" : "abc"
        },
        "C" : {
            "mandatory" : false,
            "type" : "text"
        }
    }
}

/* 5 */
{
    "_id" : 5,
    "name" : "xyz",
    "age" : 23,
    "type" : 2,
    "points" : {
        "B" : {
            "mandatory" : false,
            "type" : "text"
        },
        "C" : {
            "values" : "C",
            "type" : "text"
        }
    }
}

/* 6 */
{
    "_id" : 6,
    "name" : "abc",
    "age" : 43,
    "type" : 1,
    "points" : {
        "A" : {
            "type" : "label",
            "values" : "abc"
        },
        "B" : {
            "mandatory" : false,
            "type" : "text"
        }
    }
}

我想要所有具有"type"="label""values"="" 字段的文档来自"points"

如何在mongoDB 中使用find() 来实现此列表?有人知道吗?

【问题讨论】:

  • 你知道A、B、C是什么吗?
  • 不,这不是解决办法。可能还有更多。它的动态字段将被添加。
  • @chridam 但建议,但我是 mongoDB 的新手。因此,如果您有任何我可以直接应用的解决方案,那就太好了。

标签: mongodb mapreduce mongodb-query


【解决方案1】:

与当前设计一样,您需要一种机制来获取集合中所有动态键的列表,例如var dynamic_keys = ["A", "B", "C"],解析此列表以创建 $or 查询,该查询如果应用于上述情况,您的最终查询基本上应该是这样的

db.collection.find({ 
    "$or": [ 
        { "points.A.type": "label", "points.A.values": "" }, 
        { "points.B.type": "label", "points.B.values": "" }, 
        { "points.C.type": "label", "points.C.values": "" } 
    ]
})

获取动态键列表的第一个操作只能通过 Map-Reduce 进行。

在 mongo shell 中运行以下 mapreduce 操作将填充一个名为 temp_collection_keys 的单独临时集合,其中所有动态键作为 _id 值:

mr = db.runCommand({
    "mapreduce": "collection",
    "map": function() {
        for (var key in this.points) { emit(key, null); }
    },
    "reduce": function() { }, 
    "out": "temp_collection_keys"
})

要获取所有动态键的列表,请在结果集合上运行 distinct:

db[mr.result].distinct("_id")
["A", "B", "C"]

现在有了上面的列表,您可以通过创建一个将在循环中设置其属性的对象来组装您的查询。通常您的 $or 文档将具有以下结构:

var orQuery = {
    "$or": [ 
        { "points.A.type": "label", "points.A.values": "" }, 
        { "points.B.type": "label", "points.B.values": "" }, 
        { "points.C.type": "label", "points.C.values": "" } 
    ]
};

因此,使用上面的子文档键列表,您可以使用原生 JavaScript 的 map() 方法动态构造上面的 $or 数组,该方法应用于 distinct 数组结果:

var mr = db.runCommand({
    "mapreduce": "collection",
    "map": function() {
        for (var key in this.points) { emit(key, null); }
    },
    "reduce": function() { }, 
    "out": "temp_collection_keys"
});

var orArray = db[mr.result].distinct("_id").map(function (key){
    var obj = { };
    obj["points."+key+".type"] = "label";
    obj["points."+key+".values"] = "";
    return obj;
}); 

db.collection.find({ "$or": orArray });

样本输出

{
    "_id" : 2,
    "name" : "bob",
    "age" : 42,
    "type" : 1,
    "points" : {
        "B" : {
            "type" : "label",
            "values" : ""
        },
        "C" : {
            "mandatory" : false,
            "type" : "text"
        }
    }
}

【讨论】:

    猜你喜欢
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-12
    • 2017-02-20
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    相关资源
    最近更新 更多