2012-01-12 2 views
19

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

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

ответ

-1

Я думаю, было бы проще, если бы вы поместили объект сервисов в массив, так что вы можете использовать $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 } ] } 
+0

я в конечном итоге изменить нашу схему, чтобы просто использовать массив. Я мог бы использовать $ elemMatch, но поскольку мне нужно было только соответствовать по одному критерию, я смог сделать: 'db.users.find ({services.credits: {$ lt: 50}})' – stuporglue

+9

-1, потому что это не ответ на вопрос. Не у всех есть возможность изменить схему данных, с которыми они работают. Этот вопрос остается без ответа. – CommaToast

+0

ОК, я ответил сам. Нашел способ сделать это. Опубликовано ниже. – CommaToast

1

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

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

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

+0

То, что я действительно хотел, было ассоциативным массивом, что помешало бы мне иметь два элемента массива для одного и того же идентификатора службы. Наши пользователи никогда не должны заканчивать «{services: [{service: f, credits 50}, {service: f, credits: 60}]}'. Ассоциативный массив обеспечивает это, и 90% наших поисковых запросов тривиальны. Использование регулярных массивов заставляет меня сначала искать массив, прежде чем делать запросы, чтобы узнать, нужно ли мне добавить массив сервисов или найти элемент и обновить его. – stuporglue

+0

Почти вся проверка согласованности должна выполняться в коде. Это справедливо и для ассоциативных массивов.MongoDB не поддерживает ограничения во встроенных документах: http://waistcode.net/blog/unique-array-keys-in-mongodb, т. Е. Объект не может «нарушать себя». – mnemosyn

+0

Это не ответ на вопрос. Замечание @ stuporglue выше объясняет совершенно правильную и вескую причину, чтобы создать свою модель данных так, как он сделал. По этой же причине наша модель данных была выполнена так, как мы ее делали. И мне все еще нужен ответ на этот вопрос. Люди, которые говорят, что не знают ответа или обвиняют людей в злоупотреблении вещами и т. Д., Просто непродуктивны. – CommaToast

15

Это реальный ответ на ваш вопрос.

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

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

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

В вашем запросе отсутствует поддержка индекса. Просто нет причин использовать такую ​​структуру данных, как это; если вы даже не можете имитировать индекс, вы каждый раз выполняете проверку коллекции, и вы можете так же загружать всю коллекцию в ОЗУ и сканировать ее там, что тогда является тривиальным упражнением в JavaScript. – mnemosyn

+7

Он спросил: «Как я могу найти все пользовательские объекты, которые имеют менее 50 кредитов для какой-либо службы, если у меня нет способа узнать, какие ключи объектов службы будут?» Я ответил на его вопрос. Я не ограничивал «ответчиков» только ответами, потому что они не были ответами. Это были люди, которые говорили: «Вы не можете/не должны этого делать», когда это ясно, и это чисто вопрос о том, нужно ли вам. Я не согласен с тем, что «нет оснований для использования такой структуры данных» ... для этого есть множество причин. Просто потому, что вы их не знаете, на самом деле это не моя вина, а не опера. – CommaToast

+4

Я не смотрю на народную репутацию. Я просто прочитал ответ. Я не сомневаюсь, что вы больше знаете о MongoDB, чем я. Но если это не ответ на вопрос, который был задан, я обязан его понизить; Я не собираюсь этого делать просто потому, что у вас высокий репутация. Говорить кому-то нет никакого способа сделать что-то, когда на самом деле есть, не круто. Говоря людям, что их структура данных бессмысленна только потому, что вы не видите смысла, тоже не круто. Возможно, у них есть отличная причина для использования, которые вы просто не понимаете. Может быть, если вы спросите, в чем дело, вы можете узнать. – CommaToast