如何查询与数组中对象的确切字段匹配的集合?
由于测试用例更明确,因此这是要通过的测试。
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 ]
我的用例是一个邀请系统,其中不存在相同的访客组合,因此当发送新邀请时,我需要检查是否具有完全相同的访客(无论他们的订单如何)。
注意:我使用Guest对象数组,因为它携带一些额外的数据。这是一个示例数据集(https://gist.github.com/anonymous/5507735)。
答案 0 :(得分:1)
也许$all
就是您所需要的。我不确定您使用的是哪个ORM或哪个架构,但这里是一个示例mongo shell输出:
> 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实现,但我不确定它是否涵盖了您的所有用例。
答案 1 :(得分:1)
根据nyde1319的回答;这感觉有点hackish,但由于这里还没有其他答案:
db.invitation.find({'guests.player':{'$all':['bbb','ccc']}, guests: {$size: 2}})
{$size: 2}
中的数字2当然取决于数组的长度。