简写版:
如果我有一个索引{"category": 1}和一个文档{"category": {type: "memory", class: "DDR400"},我如何才能执行像{"category.type": "memory"}这样的使用我的索引的查询?
长版本:
对于MongoDB,我希望使用嵌入式文档作为索引的键。
例如,我可能有一些类似这样的文档(对于假设的产品数据库):
{"category": {"type": "hard-drive", "form_factor": "2.5in", "size": "500GB"}, ...}
{"category": {"type": "hard-drive", "form_factor": "3.5in", ...}, ...}
{"category": {"type": "memory", "class": "DDR400", ...}, ...}对于上述示例,我可能需要执行如下查询:
{"category.type": "hard-drive"}
{"category.type": "hard-drive", "category.form_factor": "2.5in"}
{"category.type": "memory"}
{"category.type": "memory", "category.class": "DDR400"}我的问题是创建一个索引。http://www.mongodb.org/display/DOCS/Indexes#Indexes-DocumentsasKeys的文档描述了两个选项:
第一个选项是创建一个复合索引,例如{ "category.type": 1, "category.class": 1 }。这对我的情况不太好,因为我可能有许多不同类型的子类别。
第二个选项是使用文档作为键:{ "category": 1 }。现在,像{"category": {"type": "memory", "class": "DDR400"}}这样的查询将使用索引,但{"category": {"type": "memory"}}将不返回任何内容,而{"category.type": "memory"}将不使用该索引。是否有一种方法可以使用此索引进行查询,从而提供与{"category.type": "memory"}相同的结果?
我怀疑使用类似{"category" {"$gt": ..., "$lt": ...}的查询应该有效,但是应该在空白处放什么呢?
发布于 2011-07-07 07:24:51
为category.type创建单独的索引(可能除了category之外)似乎是最好的选择。
您可以使用$gt和$lt的范围查询。这些方法只适用于嵌入对象的二进制表示,它只适用于第一个(按存储顺序排列)字段,而且只有当第一个字段在所有文档中相同时才能工作,因此它不是很灵活,而且很容易中断。
{"category" : {"$gt": {"type": "memory"}, "$lt": {"type": "memoryX" } } }这里的"memoryX“是一个断点:所有带有”内存“的东西都会在此之前排序。
请注意,这要求"type“字段是所有具有”type“字段的文档的二进制表示的第一个字段。它也只适用于"type“字段(无法查询第一个位置上的其他字段,必须先选择一个字段),因此与专用的"category.type”索引相比几乎没有优势(只是节省了空间)。
我之前尝试过这个想法,参见邮件列表上的这个线程。它确实有效,但你必须小心你正在做的事情:
它是支持和稳定的。许多切分/复制内部程序使用嵌入文档的_id值。 这里唯一要注意的是嵌入式元素中键的排序。它们按照二进制表示进行排序,因此{x:1,y:1}与{y:1,x:1}不同,排序也不同。它们不仅排序不同,而且是不同的价值观。默认情况下,有些语言总是对字典/散列/映射中的键进行排序。
同样,考虑在您需要的字段上创建额外的索引。
在我的例子中,我只需要查询'a','a,b‘或'a,b,c',或者'a,x,y',其中包含x的文档从来不包含'b’或'c‘。
那样的话可能会管用。不过,我仍然会做两个复合索引a,b和a,x。或许只有b和x。考虑到文档包含b或x,您可能已经有效地过滤掉了与a有关的无关文档( form_factor = 2.5in已经告诉您它是硬盘,class = DDR400已经使它成为内存)。在通过a,b进行过滤之后,您可能不需要索引来进一步深入c。
通过对二进制表示使用这个棘手的查询,您将依赖于可以称为实现细节的内容。你可能会受到一些司机的打击,他们喜欢重新订购字段,或者像本期一样,有时会对Mongo本身进行重组。
发布于 2011-07-07 08:14:30
如果您要搜索的每个“类型”都有一个基本属性,那么只需添加一个单独的字段,并创建一个复合索引,例如:
{"category": {"type": "hard-drive", "form_factor": "2.5in", "searchfield: "2.5in", ...}, ...}
{"category": {"type": "memory", "class": "DDR400", searchfield: "DDR400", ...}, ...}如果您正在搜索多个字段,但这些字段的值不同,则可以将值添加为标记,并再次创建一个复合键:
{"category": {"type": "hard-drive", "form_factor": "2.5in", "size": "500GB", "tags": ["2.5in", "500GB"]}, ...}
{"category": {"type": "memory", "class": "DDR400", "tags": ["DDR400"], ...}, ...}https://stackoverflow.com/questions/6607127
复制相似问题