Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.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查询_Mongodb - Fatal编程技术网

使用嵌入式文档作为键的MongoDB查询

使用嵌入式文档作为键的MongoDB查询,mongodb,Mongodb,短版: 如果我有一个索引{“category”:1},和一个文档{“category”:{type:“memory”,class:“DDR400”},我如何执行使用我的索引的查询,例如{“category.type:“memory”} 长版本: 对于MongoDB,我希望使用嵌入文档作为索引的键 例如,我可能有这样一些文档(对于一个假设的产品数据库): 对于上述示例,我可能希望执行以下查询: {"category.type": "hard-drive"} {"category.type": "h

短版:

如果我有一个索引
{“category”:1}
,和一个文档
{“category”:{type:“memory”,class:“DDR400”}
,我如何执行使用我的索引的查询,例如
{“category.type:“memory”}

长版本:

对于MongoDB,我希望使用嵌入文档作为索引的键

例如,我可能有这样一些文档(对于一个假设的产品数据库):

对于上述示例,我可能希望执行以下查询:

{"category.type": "hard-drive"}
{"category.type": "hard-drive", "category.form_factor": "2.5in"}
{"category.type": "memory"}
{"category.type": "memory", "category.class": "DDR400"}
我的问题是创建索引。位于的文档介绍了两个选项:

第一个选项是创建一个复合索引,例如
{“category.type”:1,“category.class”:1}
。这对我的情况不起作用,因为我可能有许多不同类型的子类别

第二个选项是使用文档作为键:
{“category”:1}
。现在像
{“category”:{“type”:“memory”,“class”:“DDR400”}
这样的查询将使用索引,但是
{“category”:{“type”:“memory”}
将不返回任何内容,
{“category.type”:“memory”}
不会使用索引。是否有一种方法可以使用此索引进行查询,从而得到与
{“category.type”:“memory”}
相同的结果


我怀疑使用诸如“代码> {”类别“{$GT”:……“$lt”:…} <代码>应该工作,但是我应该把它放在空白空间中的什么?< /p> < p>创建一个单独的索引>代码>类别。类型< /代码>(可能除了<代码>类别>代码>)似乎是最好的选择。 您可以将范围查询与

$gt
$lt
一起使用。这些查询适用于嵌入对象的二进制表示形式,它只适用于第一个(按存储顺序)字段,并且仅当所有文档中的第一个字段都相同时才有效,因此它不是很灵活,也很容易被破坏

   {"category"  : {"$gt": {"type": "memory"},  "$lt": {"type": "memoryX" } } }
这里的“memoryX”是一个分界点:所有带有“memory”的东西都会在这之前排序

请注意,这要求“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本身的操作,有时会对内容进行重新排序。

如果您正在为每个“类型”搜索一个基本属性,然后简单地添加is作为一个单独的字段,并创建一个复合索引,例如:

{"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"], ...}, ...}

我的问题是,我可能在类别中有许多不同的键,并且我无法为它们中的每一个创建索引。我总是从左到右查询嵌入文档中的键(因此永远不会只查询最后一个键)您的GT和$LT的解决方案似乎是可行的,但是在哪些情况下它可以破解?您只需要在要查询的关键字上创建索引。如果有很多组合,查询“从键到右”可能也不太好。考虑{a:1,b:1,c:1 } vs {a::1,c:1 } vs {b:1,c:1 }。。您无法使用这些文档查询a、b、c的所有组合。“您使用$gt和$lt的解决方案似乎有效,但在哪些情况下会中断?”:它要求“类型”字段是所有文档二进制表示形式中的第一个字段。它也仅适用于“类型”字段,因此与专用的“category.type”索引相比几乎没有优势(仅节省空间)。这样的查询怎么样:
{“category”:{“$gt”:{“type”:“hard drive”,“form_factor”:“2.5in”},$lt:{“type”:“hard drive”,“form_factor”:“2.5inX”}}
我喜欢这个解决方案。我甚至可以将所有内容都作为标记放置:{“标记”:[“硬盘驱动器”、“2.5in”、“500GB”]}、{“标记”:[“内存”、“DDR400”]},或者如果可能存在冲突,则在标记“类型”之前加上前缀,例如“内存-DDR400”“。如果我需要搜索多个标记,$all运算符将用于我的查询。我接受了Thilo的答案,因为它回答了我最初的问题并解释得很好。但是,我可能最终会使用此解决方案。+1.这很好。特别是因为你可以使用$a
{"category": {"type": "hard-drive", "form_factor": "2.5in", "size": "500GB", "tags": ["2.5in", "500GB"]}, ...}
{"category": {"type": "memory", "class": "DDR400", "tags": ["DDR400"], ...}, ...}