MongoDB范围查询整个嵌入式文档的值 [英] MongoDB range query on entire embedded document value

查看:124
本文介绍了MongoDB范围查询整个嵌入式文档的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个索引为{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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆