【问题标题】:Mongodb find a document with all subdocuments satisfying a conditionMongodb找到一个所有子文档都满足条件的文档
【发布时间】:2020-03-11 07:29:32
【问题描述】:

我的数据库中有游戏收藏:

var game = {
  players: [{username:"user1", status:"played"},
            {username:"user2", status:"accepted"}]
}

据我了解,这样的查询:db.games.find({"players.status":"played"}) 将为我提供至少一名玩家状态为“已玩”的所有游戏。如何找到所有玩家状态为“已玩”的游戏?

【问题讨论】:

标签: mongodb


【解决方案1】:

如果您只有“已玩”以外的一种状态,请使用查询:

db.games.find({ "players.status": { $ne:"accepted" } })

您可以调整查询以处理更多状态值,只要它们在查询时都是已知的。

【讨论】:

  • 我就是这样做的。仍然想知道是否有更好的方法,因为现在我每次添加新游戏状态时都必须更改查询。
  • 您可以使您的查询动态化 - 如果您将一组所有状态值创建为一个数组,请从中删除“已播放”并将其与 $nin(未在)操作一起使用,它应该可以工作。
  • 谢谢,我想这是我能做到的唯一方法。
【解决方案2】:

我也遇到了这个问题。我试图使用$all 并且几乎没有进展。它有助于改变我对这个问题的看法并改用$not。我wrote about what I found here

在您的情况下,您应该能够执行以下操作:

db.games.find({
  players: {
    $not: {
      $elemMatch: {
        status: { $ne: "played" }
      }
    }
  }
})

查找播放器状态不等于"played" 的所有文档,并返回该集合的倒数。这样做的好处是您永远不必担心添加更多状态值。

【讨论】:

    【解决方案3】:

    使用聚合框架的$unwind特性:

    db.collection.aggregate([{$unwind:"$players.status"},{$match:{"players.status":"played"},{$project:{"_id":0," player.status":1}}])

    (查看此答案:https://stackoverflow.com/a/15082321/1214167

    【讨论】:

    • 这与 OP 想要的不匹配 - 这将只返回状态为“已播放”的球员 - 问题是返回所有球员都参加过比赛的球队。您可以通过扩展查询来计算玩过的玩家数量并将其与完整数组的大小进行比较来进行聚合,但这比简单的查找更复杂且更慢。
    猜你喜欢
    • 2016-04-23
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    相关资源
    最近更新 更多