MongoDB范围查询整个嵌入式文档的值 [英] MongoDB range query on entire embedded document value
问题描述
假设我们有一个索引为{tag: 1}
的集合foo
,其中tag
是单个键值对(在我的实际用例中有很多详细信息,但是我试图简化问题):
Assume we have a collection foo
with index {tag: 1}
where tag
is a single key-value pair (there are a lot more details in my actual use-case, but I'm trying to distill down the problem):
{_id: 1, tag: {bar: "BAR"}}
{_id: 2, tag: {baz: "BAZ"}}
当我查询{tag: { $gte: { baz: MinKey() }}}
时,它将返回两个文档(意外).
When I query {tag: { $gte: { baz: MinKey() }}}
, it returns BOTH documents (unexpected).
当我查询{tag: { $gte: { baz: "" }}}
时,它仅返回{_id: 2, tag: {baz: "BAZ"}}
(预期).
When I query {tag: { $gte: { baz: "" }}}
, it returns only {_id: 2, tag: {baz: "BAZ"}}
(expected).
根据 https://docs.mongodb. com/manual/reference/bson-type-comparison-order/#objects ,BSON对象按以下顺序排序:1)通过字段名称,2)通过字段值.
According to https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#objects, BSON objects are ordered: 1) by field names and 2) by field values.
那么,当bar
不大于baz
时,为什么{tag: { $gte: { baz: MinKey() }}}
返回{_id: 1, tag: {bar: "BAR"}}
吗?
So why does {tag: { $gte: { baz: MinKey() }}}
return {_id: 1, tag: {bar: "BAR"}}
when bar
is NOT GREATER THAN baz
?
推荐答案
请注意在您链接的文档中的以下几行命令:
Note the command a few lines down in the documentation you linked:
不存在的字段
比较将不存在的字段视为空BSON对象.这样,对文档{}和{a:null}中的a字段进行排序将按排序顺序将文档视为等效.
The comparison treats a non-existent field as if it were an empty BSON Object. As such, a sort on the a field in documents { } and { a: null } would treat the documents as equivalent in sort order.
这是在告诉您,不存在的字段和设置为null的字段会被特别对待.
This is telling you that non-existent fields and fields set to null are treated specially.
为了使文档{}
和{a: null}
在排序顺序上等效,排序算法必须考虑到缺少的排序字段,并且该字段的值为null
.
In order for the documents {}
and {a: null}
to be equivalent in sort order, the sort algorithm must be considering the missing sort field to be present, and have a value of null
.
如果您明确添加缺少的字段,只是为了看看它的外观,那么排序就更有意义了.
If you explicitly add the missing field, just to see how it looks, the ordering makes more sense.
应用于{_id: 1, tag: {bar: "BAR"}}
的过滤器{tag: { $gte: { baz: MinKey() }}}
本质上是将{baz: MinKey()}
与{baz: null, bar: "BAR"}
进行比较.
The filter {tag: { $gte: { baz: MinKey() }}}
applied to {_id: 1, tag: {bar: "BAR"}}
is essentially comparing {baz: MinKey()}
with {baz: null, bar: "BAR"}
.
在链接的文档的顶部附近,它指出MinKey
小于null
,因此这是正确的顺序.
Near the top of the documentaion you linked it states that MinKey
is less than null
, so that is the proper ordering.
编辑
通常,当字段名称本身不是数据时,查询效率最高.就表格数据库而言,哪一列将包含"baz"?
In general, querying is most efficient when the fieldnames are not themselves data. In terms of a tabular database, which columnn would contain "baz"?
模式中的微小变化将简化这种类型的查询.代替{tagname: tagvalue}
,使用{k:tagname, v:tagvalue}
.然后,您可以索引tag.k
和/或tag.v
,并在tag.k
上查询以找到带有"baz"的所有文档.标签,使用不等式操作查询标签将更加直观.
A slight change in the schema would simplify this type of query. Instead of {tagname: tagvalue}
, use {k:tagname, v:tagvalue}
. You could then index tag.k
and/or tag.v
, and query on tag.k
to find all documents with a "baz" tag, querying tags with inequality operations would work more intuitively.
db.collection.find({"tag.k":{$gte:"baz"}})
完全匹配可以使用elemMatch之类的
Exact matches could be done with elemMatch like
db.collection.find({tag: {$elemMatch:{k:"baz",v:"BAZ"}}})
如果您确实需要返回的文档包含{tagname: tagvalue}
,则$arrayToObject
聚合运算符可以执行以下操作:
If you really need the returned documents to contain {tagname: tagvalue}
, the $arrayToObject
aggregation operator can do that:
db.collection.aggregate([
{$match: {
"tag.k": {$gte: "baz"}
}},
{
$addFields: {
tag: {$arrayToObject: [["$tag"]]}
}}
])
这篇关于MongoDB范围查询整个嵌入式文档的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!