Mongodb точка подстановки обозначения? - PullRequest
22 голосов
/ 12 января 2012

У меня есть коллекция пользователей, каждый из которых может быть подписан на один или несколько сервисов. Каждый сервис имеет некоторые метаданные, в том числе количество кредитов, которые пользователь имеет для этого сервиса.

Как найти все объекты пользователя, которые имеют менее 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

Ответы [ 3 ]

17 голосов
/ 17 ноября 2014

Это фактический ответ на ваш вопрос.

Как найти все объекты пользователя, у которых менее 50 кредитов для какой-либо услуги, если у вас нет возможности узнать, какими будут ключи объектов службывыглядит следующим образом.

Используйте запрос $ где:

db.users.find({
    $where: function () {
        for (var index in this.services)
            if (this.services[index].credits < 50)
                return this;
    }
});
1 голос
/ 12 января 2012

Я не знаю, как это сделать, используя схему, которую вы используете.Мне кажется, вы злоупотребляете объектами как массивами.Если бы services был массивом (множественное число подсказывает, что так и должно быть), вы могли бы просто запросить

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

или использовать $elemMatch, если вам нужно сопоставить несколько условий для одного элемента массива.*

0 голосов
/ 12 января 2012

Я думаю, было бы проще, если бы вы поместили этот объект служб в массив, поэтому вы можете использовать $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 } ] }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...