2013-05-02 3 views
1

Как запросить коллекцию, которая соответствует точным полям объектов в массиве?Как запросить коллекцию, которая соответствует точным полям объектов в массиве

Поскольку тестовый пример более явный, вот тест, который нужно пройти.

a = Invitation.create(guests: [ Guest.new(player: 'bbb'), Guest.new(player: 'ccc') ]) 
b = Invitation.create(guests: [ Guest.new(player: 'ccc'), Guest.new(player: 'bbb') ]) 
c = Invitation.create(guests: [ Guest.new(player: 'bbb'), Guest.new(player: 'ccc'), Guest.new(player: 'ddd') ]) 

# Request to find invitation with bbb and ccc as player_id of guests, regardless the order. 
result = Invitation.collection.find(...) 
assert_equal result, [ a, b ] 

Мой случай использования является приглашение системы, где же сочетание гостей, которые не могут существовать, поэтому, когда новое приглашение отправляется, мне нужно проверить, если один с теми же самыми гостями (независимо от их порядка).

Примечание: Я использую массив гостевых объектов, так как он содержит некоторые дополнительные данные. Вот пример набора данных (https://gist.github.com/anonymous/5507735).

+0

Можете ли вы привести пример записи из монго? db.Invitation.findOne() сделал бы трюк. – shargors

+0

Я отредактировал сообщение, чтобы добавить пример набора данных (https://gist.github.com/anonymous/5507735). –

ответ

1

На основании ответа nyde1319; это чувствует себя немного хака, но так как нет никаких других ответов здесь идет:

db.invitation.find({'guests.player':{'$all':['bbb','ccc']}, guests: {$size: 2}}) 

Номер 2 в {$size: 2} конечно, зависит от длины массива.

+0

Хорошо работает. Благодаря! –

1

Возможно, $all - это то, что вам нужно. Я не уверен, ORM или что схемы вы используете, но вот пример вывода Монго оболочки:

> db.invitation.find({'guests.player':{'$all':['bbb','ccc']}}) 
{ "_id" : ObjectId("518319079468428b381d3563"), "guests" : [ { "player" : "bbb" }, { "player" : "ccc" } ] } 
{ "_id" : ObjectId("518319239468428b381d3566"), "guests" : [ { "player" : "ccc" }, { "player" : "bbb" } ] } 
{ "_id" : ObjectId("518319b39468428b381d3567"), "guests" : [ { "player" : "ccc" }, { "player" : "bbb" }, { "player" : "ddd" } ] } 

Если вы хотите только те, которые содержат 'bbb' и 'ccc' только, вы можете попробовать следующее:

db.inv.find({'guests.player':{$all:['bbb','ccc']}, 
    'guests':{$not:{$elemMatch:{'player':{$nin:['bbb','ccc']}}}}}) 

, который дает:

[ 
    { "_id" : ObjectId("518319079468428b381d3563"), 
     "guests" : [ { "player" : "bbb" }, { "player" : "ccc" } ] }, 
    { "_id" : ObjectId("518319239468428b381d3566"), 
     "guests" : [ { "player" : "ccc" }, { "player" : "bbb" } ] } 
] 

Если вы хотите 'bbb' и 'ccc', просто замените $all с $in. Это как-то реализация XOR, но я не уверен, что она охватывает весь ваш прецедент.

+0

Проблема в том, что я не хочу третьей записи. Мне нужны только приглашения с точными игроками BBB и CCC (независимо от порядка). Я не хочу содержать BBB, CCC и DDD. –

+0

См. Мое редактирование. – MervS

+0

Спасибо. Я считаю, что ответ от Юхо - лучший способ пойти. –

Смежные вопросы