如何查询与数组中对象的确切字段匹配的集合

时间:2013-05-02 17:18:36

标签: mongodb

如何查询与数组中对象的确切字段匹配的集合?

由于测试用例更明确,因此这是要通过的测试。

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)。

2 个答案:

答案 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当然取决于数组的长度。