MongoDB基于属性值的嵌套元素查询

时间:2014-09-05 16:11:36

标签: mongodb mongodb-query

对于下面的mongo文档,我正在尝试编写投影查询。给定userId值的输入和目标的ObectId(例如下面的文档中的54073d80e4b0cbf1ce225f02),如何找到具有这些值的文档?

我搜索的所有示例都希望用户知道要查询的“属性”名称。在这种情况下,“target”元素中的属性名称不是提前知道的。它们可以是my-target-1,my-target-2等。所以我想根据属性的值搜索文档(54073d80e4b0cbf1ce225f02)。有什么建议吗?

{
    "_id" : ObjectId("540786bbe4b0e4752fe93321"),
    "name" : "foo name",
    "userId" : "123456",
    "targets" : {
        "my-target-1" : { //my-target-1 is dynamic property.
            "executionOrder" : {
                "1" : { //"1" is dynamic property.
                    "_id" : ObjectId("54073d80e4b0cbf1ce225f02"),// this is my search key
                    "type" : "TYPE 1",
                    "version" : "2"
                },
             "2" : {
                    "_id" : ObjectId("54073d80e4b0cbf1ce225f03"),
                    "type" : "TYPE 2",
                    "version" : "2"
                }
            }
        },
        "my-target-2" : {
            "executionOrder" : {
                "1" : {
                    "_id" : ObjectId("54073d80e4b0cbf1ce225f04"),
                    "type" : "TYPE 1",
                    "version" : "2"
                },
             "2" : {
                    "_id" : ObjectId("54073d80e4b0cbf1ce225f05"),
                    "type" : "TYPE 2",
                    "version" : "2"
                }
            }
        }
    },

2 个答案:

答案 0 :(得分:1)

其中一个解决方案是使用MongoDB的文本搜索功能来实现这一目标,

  

要允许对包含字符串内容的字段进行文本搜索,请使用   通配符说明符($ **),用于索引包含字符串的所有字段   内容。

     

以下示例索引每个数据中的任何字符串值   集合中每个文档的字段,并将索引命名为TextIndex:

db.collection.ensureIndex(
{ "$**": "text" }
)

并查询任何字段中的任何文本,下面将返回文档中的任何字段或其子文档与查询字符串匹配的所有文档。

db.collection.aggregate([{$match:{$text:{$search:"searchString"}}}])

注意:如果您使用字符串内容对文本字段进行索引,则搜索将仅返回结果。

请记住,

  

查询匹配完整的词干。例如,如果是   文档字段包含单词blueberry,搜索术语blue   与文件不符。但是,搜索蓝莓或   蓝莓会匹配

您需要明智地使用它来满足您的要求。

因此,在上面的示例中,在子文档中,您可以搜索唯一且文本化的字段。

"_id" : ObjectId("54073d80e4b0cbf1ce225f02") //不要查询此字段。

而是查询"type" : "TYPE 1".

另见:

Create text index on sub-document field wildcard

答案 1 :(得分:1)

如果要查找包含特定值的文档,可以将$ where子句与函数一起使用。下面的查询创建了一个函数,该函数在不知道属性的情况下迭代查找特定值的所有属性和值。

 {$where: function() {
        var deepIterate = function  (obj, value) {
            for (var field in obj) {
                if (obj[field] == value){
                    return true;
                }
                var found = false;
                if ( typeof obj[field] === 'object') {
                    found = deepIterate(obj[field], value)
                    if (found) { return true; }
                }
            }
            return false;
        };
        return deepIterate(this, "573c79aef4ef4b9a9523028f")
    }}

当然,您可以修改查询以匹配某些键和值的对。就像这样:

 {$where: function() {
        var deepIterate = function  (obj, tested) {
            for (var field in obj) {

                if (field == tested[0]){
                    if (obj[field] == tested[1]){
                        return true;
                    }
                }

                var found = false;
                if ( typeof obj[field] === 'object') {
                    found = deepIterate(obj[field], tested)
                    if (found) { return true; }
                }
            }
            return false;
        };
        return deepIterate(this, ["myKey", "myvalue"])
    }}

显然,您可以修改函数以查询对象内的许多匹配键和值对。天空是极限。