Mongodb用于键值对索引的最佳模式设计

时间:2014-07-01 14:50:42

标签: mongodb indexing

我自己找到这个问题的答案时遇到了一些困难:

在mongo文档中存储键/值对的最佳方法是什么,并在其上放置索引以执行多标准搜索。

我有一个存储在mongo数据库中的文档,如下所示:

{
_id:xxxxxxxxxx,
name : "x1",
tags : [
    {key:"color", value:"blue"},
    {key:"size", value:"L"},
    {key:"weight", value:5}
]
}

“tags”属性的每个键都是唯一的(每个文档的颜色或大小不能超过1个),每个键都是optionnal(我可以指定没有“color”的文档)。

根据"Indexes FAQ",我创建了一个这样的索引:

{
    "tags.key":1, "tags.value":1
}

要对此索引执行查询,我使用此查询(返回所有蓝色项目):

.find({
    tags:{$elemMatch:{"key":"color","value":"blue"}}
})

explain()显示查询使用索引。好!

但是现在,如果我想进行多标准搜索,我会使用此查询(返回所有大小为“L”的蓝色项目):

.find({
    $and:[
        {tags:{$elemMatch:{"key":"color","value":"blue"}}},
        {tags:{$elemMatch:{"key":"size","value":"L"}}}
    ]
})

此查询正在运行,但执行计划显示的IXSAN扫描的文档多于返回的数量:

{
"cursor" : "BtreeCursor Keys",
"isMultiKey" : true,
"n" : 22,
"nscannedObjects" : 53,
"nscanned" : 53,
"nscannedObjectsAllPlans" : 53,
"nscannedAllPlans" : 109,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 2,
"indexBounds" : {
    "tags.key" : [ 
        [ 
            "color", 
            "color"
        ]
    ],
    "tags.value" : [ 
        [ 
            "blue", 
            "blue"
        ]
    ]
},
"server" : "BLABLABLA:27017",
"filterSet" : false,
"stats" : {
    "type" : "PROJECTION",
    "works" : 55,
    "yields" : 0,
    "unyields" : 0,
    "invalidates" : 0,
    "advanced" : 22,
    "needTime" : 0,
    "needFetch" : 0,
    "isEOF" : 1,
    "children" : [ 
        {
            "type" : "KEEP_MUTATIONS",
            "works" : 55,
            "yields" : 0,
            "unyields" : 0,
            "invalidates" : 0,
            "advanced" : 22,
            "needTime" : 31,
            "needFetch" : 0,
            "isEOF" : 1,
            "children" : [ 
                {
                    "type" : "FETCH",
                    "works" : 54,
                    "yields" : 0,
                    "unyields" : 0,
                    "invalidates" : 0,
                    "advanced" : 22,
                    "needTime" : 31,
                    "needFetch" : 0,
                    "isEOF" : 1,
                    "alreadyHasObj" : 0,
                    "forcedFetches" : 0,
                    "matchTested" : 22,
                    "children" : [ 
                        {
                            "type" : "IXSCAN",
                            "works" : 53,
                            "yields" : 0,
                            "unyields" : 0,
                            "invalidates" : 0,
                            "advanced" : 53,
                            "needTime" : 0,
                            "needFetch" : 0,
                            "isEOF" : 1,
                            "keyPattern" : "{ tags.key: 1.0, tags.value: 1.0 }",
                            "boundsVerbose" : "field #0['tags.key']: [\"color\", \"userid\"], field #1['Keys.v']: [\"4189\", \"4189\"]",
                            "isMultiKey" : 1,
                            "yieldMovedCursor" : 0,
                            "dupsTested" : 53,
                            "dupsDropped" : 0,
                            "seenInvalidated" : 0,
                            "matchTested" : 0,
                            "keysExamined" : 53,
                            "children" : []
                        }
                    ]
                }
            ]
        }
    ]
}
}

似乎在IXSCAN中只考虑了第一个$ elemMatch。

那么,有没有办法改善这个或没有? 要么通过更改我的文档设计来更改查询?

欢迎您的帮助!

佛瑞德

0 个答案:

没有答案