【问题标题】:Mongodb dot notation wildcard?Mongodb点符号通配符?
【发布时间】:2012-01-12 18:30:30
【问题描述】:

我有一组用户,每个用户都可能订阅一项或多项服务。每个服务都有一些元数据,包括用户对该服务的信用数量。

如果我无法知道服务对象的键是什么,我如何才能找到所有对某些服务的积分少于 50 的用户对象?

从概念上讲,它会是这样的,这是行不通的:

db.users.find({services.*.credits : {$lt : 50}})

用户集合:

   {
_id: 4f0ea25072139e4d2000001f,
services : {
    a : { credits : 100, score : 2000 },
    b : { credits : 200, score : 300 },
    c : { credits : 10, score : 1300 }
    }
},
{
_id: 4f0ea25072139e4d2000001f,
services : {
    f : { credits : 68, score : 14 },
    q : { credits : 1000, score : 102 },
    z : { credits : 59, score : 352 }
    }
}

我想做的另一个例子,如果这里不清楚,在这里解释:http://www.mongodb.org/display/DOCS/Advanced+Queries#comment-346075854

【问题讨论】:

    标签: mongodb syntax


    【解决方案1】:

    这是对您问题的实际答案。

    如果您无法知道服务对象的键是什么,如何找到所有对某些服务少于 50 积分的用户对象。

    使用 $where 查询:

    db.users.find({
        $where: function () {
            for (var index in this.services)
                if (this.services[index].credits < 50)
                    return this;
        }
    });
    

    【讨论】:

    • 您的“查询”完全缺乏索引支持。没有理由使用这样的数据结构;如果您甚至无法模拟索引,那么您每次都在执行集合扫描,您也可以将整个集合加载到 RAM 中并在那里进行扫描,这在 JavaScript 中是一个简单的练习。
    • 他问道:“如果我无法知道服务对象的键是什么,我如何才能找到所有对某项服务的信用少于 50 的用户对象?”我回答了他的问题。我并没有仅仅对答案投反对票,因为它们不是答案。他们是人们说,“你不能/不应该这样做”,而你显然可以这样做,而你是否应该这样做纯粹是一个见仁见智的问题。我不同意“没有理由使用这样的数据结构”......有很多很好的理由这样做。仅仅因为你不认识他们,真的不是我的错,也不是我的错。
    • 我不看人们的代表我只是读了答案。我不怀疑你比我更了解 MongoDB。但是,如果这不是对所提出问题的回答,那么我有义务否决它;我不会仅仅因为你的声望很高而不这样做。告诉某人没有办法做某事,而事实上有,这并不酷。告诉人们他们的数据结构是没有意义的,只是因为你没有看到它的意义,这也不酷。也许他们有充分的理由使用它,而您根本不了解。也许如果你问有什么意义,你可能会学到。
    • 我完全同意@CommaToast 在这里所说的话。我需要运行一次性查询来确定数据库中是否缺少某些数据,以确定是否需要进行代码更改。数据库已经存在,并且数据结构没有任何问题。我没有办法更新预先存在的数据结构来追踪几个小问题。建议这样做有利于提供实际解决方案是完全无知的。
    【解决方案2】:

    我不知道使用您正在使用的架构来完成此操作的方法。在我看来,您正在滥用对象作为数组。如果services 是一个数组(应该是复数提示),您可以简单地查询

    db.users.find({"services.credits" : { $lt : 50 }}); 
    

    如果您需要在单个数组元素上匹配多个条件,请使用$elemMatch

    【讨论】:

    • 我真正想要的是关联数组,这会阻止我为同一个服务 ID 拥有两个数组元素。我们的用户不应该以{services:[{service:f,credits 50},{service:f,credits:60}]} 结尾。关联数组强制执行此操作,并使我们 90% 的查找变得微不足道。使用常规数组迫使我在进行查询之前先搜索数组,看看我是否需要添加到服务数组或查找元素并更新它。
    • 几乎所有的一致性检查都必须在代码中完成。对于关联数组也是如此。 MongoDB 不支持嵌入文档中的约束:waistcode.net/blog/unique-array-keys-in-mongodb,即对象不能“违反自身”。
    • 这不是问题的答案。 @stuporglue 的上述评论解释了以他的方式创建数据模型的完全有效和充分的理由。这与我们的数据模型按照我们的方式完成的原因相同。我仍然需要这个问题的答案。人们说他们不知道答案,或者指责人们滥用事物等等,都是徒劳的。
    【解决方案3】:

    我认为如果将服务对象放入数组中会更容易,因此您可以使用$elemMatch,例如:

    {
      services : [
        {key: "a" , credits : 100, score : 2000 },
        {key: "b", credits : 200, score : 300 },
        {key: "c", credits : 10, score : 1300 }
      ]
    }
    

    {
      _id: 4f0ea25072139e4d2000001f,
      services : [
        {key: "f", credits : 68, score : 14 },
        {key: "q", credits : 1000, score : 102 },
        {key: "z", credits : 59, score : 352 }
      ]
    }
    

    那么你要写的查询是这样的:

    db.coll.find({services: {$elemMatch : {credits: {$lt: 50}}}});
    

    结果:

    { "_id" : ObjectId("4f0f2be07561bf94ea47eec4"), "services" : [  {   "key" : "a", "credits" : 100, "score" : 2000 }, { "key" : "b", "credits" : 200, "score" : 300 },    {   "key" : "c",    "credits" : 10,     "score" : 1300 } ] }
    

    【讨论】:

    • 我最终将架构更改为仅使用数组。我本可以使用 $elemMatch,但由于我只需要匹配一个条件,因此我能够做到:db.users.find({services.credits : {$lt:50}})
    • -1 因为这不是问题的答案。并非每个人都有能力更改他们正在使用的数据的架构。这个问题仍然没有答案。
    • 好的,我自己回答了。找到了一种方法来做到这一点。发布在下面。
    猜你喜欢
    • 2011-05-07
    • 2016-05-26
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    相关资源
    最近更新 更多