【问题标题】:Query for documents which have an internal sub-field of a given value查询具有给定值的内部子字段的文档
【发布时间】:2016-04-10 01:00:22
【问题描述】:

我在 MongoDB 的 x 集合中有这样的文档:

{
    "_id" : ...
    "attrKeys": [ "A1", "A2" ],
    "attrs" : {
        "A1" : {
            "type" : "T1",
            "value" : "13"
        },
        "A2" : {
            "type" : "T2",
            "value" : "14"
        }
    }
}

上面的A1A2 元素只是示例:attrs 字段可以包含任意数量的任意名称的键。 attrs 中的键名存储在 attrNames 字段中。

我想查询具有attr 和给定值的子字段的文档。例如,查询在attr 键映射中有一个元素的文档,其子字段type 是“T4”。像这样的:

db.x.find({"attrs.$any.type": "T4"})

(avobe 不是合法的 MongoDB 查询语言,但我认为它可以帮助理解这个想法)。

MongoDB 可以进行该查询吗?如果 MongoDB 不支持该查询,是否有任何解决方法?谢谢!

编辑:数据模型的原始版本使用attrs 的数组而不是键映射。但是,为了允许对同一个文档进行并发修改,这种情况发生了变化,转而支持键映射。

我的意思是,使用键映射,两个独立的客户端可以修改 attrs 元素,因为一个客户端可以修改 db.x.update({_id: "y"}, {$set: { "attrs.A1.value": "12" } },另一个客户端可以修改 db.x.update({_id: "y"}, {$set: { "attrs.A2.value": "55" } },而不会相互干扰。

在使用数组的情况下,并发访问要困难得多。关于如何完成的任何提示?

【问题讨论】:

  • 关于“关于如何[使用数组进行并发访问]的任何提示?”如果社区认为更好,我可以单独提问。
  • 您认为并发访问的问题究竟出在哪里?解释为什么你认为数组会导致问题。
  • 我已经在一个单独的问题stackoverflow.com/questions/31643054/… 中详细说明了这个问题。感谢您的帮助!

标签: mongodb mongodb-query


【解决方案1】:

这在 MongoDB 中一直是可能的,因为一直有能力使用 JavaScript evaluation 构造查询条件:

db.attrs.find(function() {
    var attrs = this.attrs;
    return Object.keys(attrs).some(function(key) {
       return attrs[key].value === "14"
    });
})

通过在文档中搜索可能的键以获得所需的值,将正确返回与此处条件匹配的文档。

但这并不是一个关于“可能”的问题,而是更多“这真的是个好主意吗”,基本答案是“否”。

数据库是善变的野兽,它们喜欢使用诸如索引之类的东西以及它们自己的预期运算符集进行优化,以使搜索尽可能高效。所以是的,您可以通过语言解释器来有效地蛮力评估每个文档的编码条件,或者您可以重新考虑您的设计模式。

数据库喜欢“顺序”,所以给它一些,因为您建议的数据有一个简单的有组织的重组:

{
    "attrs" : [
        { "key": "A1", "type" : "T1", "value" : "13" },
        { "key": "A2", "type" : "T2", "value" : "14" }
     ]
}

以这种方式组织查询变得如此简单:

db.attrs.find({ "attrs.value": "14" })

当然可以支持和使用数组中子文档的任何这些属性的索引。

MongoDB毕竟是一个“数据库”,和所有数据库一样,它最关心的是它的属性的“值”,而不是使用它的“键”的名称进行搜索。因此,表示有意义的“数据”的东西不应该是“键”名称的一部分,而应该是作为“标识符”的“键”的“值”,如上所示。

对要查询的数据拥有一致的路径是在 MongoDB 中处理数据的最佳方式。使用键名不断变化的结构,除了运行代码之外不能被其他任何东西遍历,这慢得多并且比使用本机操作和索引等设施更差性能。

【讨论】:

  • 谢谢你这么详细的回答!正如您所解释的,为attrs 使用数组可能会使查询更容易,但是在我的应用程序中不使用数组是有原因的(我已经编辑了原始问题以进行详细说明)。
  • 与此相关,我在stackoverflow.com/questions/9200399/… 发现“根据我的经验,如果对象具有自然 ID,则对象数组模式不是最佳的”(在这种情况下,自然 ID 是attr 的“key”,例如 A1、A2 等)。
猜你喜欢
  • 1970-01-01
  • 2019-09-08
  • 2011-09-02
  • 2019-09-21
  • 2018-12-01
  • 1970-01-01
  • 2015-09-02
  • 2019-11-03
  • 2019-07-27
相关资源
最近更新 更多