【问题标题】:Pymongo find value in subdocumentsPymongo 在子文档中找到价值
【发布时间】:2018-09-18 14:58:43
【问题描述】:

我正在使用 MongoDB 4 和 Python 3。我有 3 个集合。第一个集合在其他集合中有 2 个引用字段。

示例:

User {
   _id  : ObjectId("5b866e8e06a77b30ce272ba6"),
   name : "John",
   pet  : ObjectId("5b9248cc06a77b09a496bad0"),
   car  : ObjectId("5b214c044ds32f6bad7d2"),
}

Pet {
   _id  : ObjectId("5b9248cc06a77b09a496bad0"),
   name : "Mickey",
}

Car {
   _id   : ObjectId("5b214c044ds32f6bad7d2"),
   model : "Tesla"
}

所以一位用户拥有一辆车和一只宠物。我需要查询 User 集合并查找是否有一个 User 拥有一个名为“Mickey”的 Pet 和一个型号为“Tesla”的 Car。

我试过这个:

db.user.aggregate([{
    $project : {"pet.name" : "Mickey", "car.model" : "Tesla"  } 
}])

但是当我只有一个包含这些数据的文档时,它会返回大量数据。我做错了什么?

【问题讨论】:

  • 预期的输出应该是什么?
  • 我只想知道该文档是否存在于我的收藏中。但输出可以只是一个布尔值或所有 User 属性

标签: python mongodb pymongo


【解决方案1】:

@AnthonyWinzlet 发布的答案的缺点是它需要翻阅用户集合中的所有文档并执行 $lookups,这是相对昂贵的。因此,根据您的 Users 集合的大小,这样做可能会更快:

  1. users.petusers.car上建立索引:db.users.createIndex({pet: 1, car: 1})
  2. cars.model上添加索引:db.cars.createIndex({model: 1})
  3. pets.name上添加索引:db.pets.createIndex({name: 1})

那么你可以简单地这样做:

  1. 获取所有匹配"Tesla"汽车的列表:db.cars.find({model: "Tesla"})
  2. 获取所有匹配"Mickey"宠物的列表:db.pets.find({name: "Mickey"})
  3. 找到您感兴趣的用户:db.users.find({car: { $in: [<ids from cars query>] }, pet: { $in: [<ids from pets query>] }})

这很容易阅读和理解,而且所有三个查询都被索引完全覆盖,因此可以期望它们尽可能快。

【讨论】:

  • 嘿。我以前已经这样做了。我有我的所有索引,我做了 3 个查询,我想尝试用一个查询来比较谁更快
【解决方案2】:

这里需要使用$lookup聚合。

类似的东西

db.users.aggregate([
  { "$lookup": {
    "from": Pet.collection.name,
    "let": { "pet": "$pet" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": ["$_id", "$$pet"] }, "name" : "Mickey"}}
    ],
    "as": "pet"
  }},
  { "$lookup": {
    "from": Car.collection.name,
    "let": { "car": "$car" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": ["$_id", "$$car"] }, "model" : "Tesla"}}
    ],
    "as": "car"
  }},
  { "$match": { "pet": { "$ne": [] }, "car": { "$ne": [] } }},
  { "$project": { "name": 1 }}
])

【讨论】:

  • 谢谢它的工作。但是查询很慢:/。有没有办法加快速度?例如,如果文档存在与否,只返回一个布尔值。我尝试了有和没有展开我有相同的结果,除了没有查询更快
  • 您的用户收藏有更多字段吗?如果是,则在此处使用投影($project),是的,我们可以在此处删除$unwind 阶段。
  • 我有 9 个字段
  • 使用投影可能会对您有所帮助...没有其他选择
  • 你能举个例子吗?
猜你喜欢
  • 2020-08-09
  • 1970-01-01
  • 2018-09-09
  • 2021-06-02
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
相关资源
最近更新 更多