【问题标题】:Mongo Project _id of Array of Documents文档数组的MongoDB项目_id
【发布时间】:2021-09-23 04:34:07
【问题描述】:

我很难编写 Mongo 查询。我永远无法理解为什么它没有返回我所期望的结果,是的,我正在阅读文档,但显然理解起来很愚蠢。

在 Compass 中,我为包含城市文档数组的 State 集合编写此查询。

{"Cities.CityName":"丹佛"}

这将返回给我的科罗拉多州文档以及文档数组中的所有城市。我下面的示例仅显示了一份城市文件,但它们都在那里。

{
"_id": {"$oid":"6146ada531696ee91a3f9fa4"},
"StateName": "Colorado",
"StateCode": "CO",
"Cities": [{
    "_id": {"$oid":"6146ada531696ee91a3f5a50"},
    "CityName": "Denver",
    "Latitude": "39.55666000",
    "Longitude": "-104.89609000"
    }...]
}

好的,所以我清楚地认为我们在 CityName 上匹配现在只需投影 City 文档的 _id。

{"Cities._id":1}

但这总是返回给我的州文件 ID,而不是匹配的城市文件 _id。

我做错了什么?

【问题讨论】:

    标签: mongodb mongodb-compass


    【解决方案1】:

    1) 您可以使用$ (projection)$elemMatch (projection)

    • 用例:位置 $ 运算符限制 <array> 的内容以返回与数组上的查询条件匹配的第一个元素。

    • 例如: { "Cities.$": 1 }或​{"Cities": { "$elemMatch": { "CityName": "Denver" } } }

    • 结果:

    {
     ​"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
     ​"Cities":[{
       ​"_id":{"$oid":"6146ada531696ee91a3f5a50"},
       ​"CityName":"Denver",
       ​"Latitude":"39.55666000",
       ​"Longitude":"-104.89609000"
     ​}]
    }
    

    Playground

    注意:您必须在投影中指定所需的结果字段!

    2) 您可以使用 $filter 聚合运算符,从 MongoDB 4.4 开始支持 find() 方法:

    • 用例:根据指定条件选择要返回的数组子集。返回一个仅包含符合条件的元素的数组。返回的元素按照原来的顺序排列。

    • 例如:

    { 
      "Cities": { 
        "$filter": { 
          "input": "$Cities", 
          "cond": { "$eq": ["$$this.CityName", "Denver"] } 
        } 
      } 
    }
    
    • 结果:
    {
     ​"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
     ​"Cities":[{
       ​"_id":{"$oid":"6146ada531696ee91a3f5a50"},
       ​"CityName":"Denver",
       ​"Latitude":"39.55666000",
       ​"Longitude":"-104.89609000"
     ​}...{}]
    }
    

    Playground

    注意:您必须在投影中指定所需的结果字段!

    2.1) 您可以使用$map 聚合运算符从Cities 数组中仅选择_ids:

    • 用例:将表达式应用于数组中的每个项目并返回一个包含应用结果的数组。

    • 例如:

    { 
      "Cities": { 
        "$map": {
          "input": {
            "$filter": { 
              "input": "$Cities", 
              "cond": { "$eq": ["$$this.CityName", "Denver"] } 
            }
          },
          "in": "$$this._id"
        }
      } 
    }
    
    • 结果:
    {
      "_id":{"$oid":"6146ada531696ee91a3f9fa4"},
      "Cities":[
        {"$oid":"6146ada531696ee91a3f5a50"},
        {"$oid":"6146ada531696ee91a3f5a51"},
        ....
      ]
    }
    

    Playground

    注意:您必须在投影中指定所需的结果字段!

    3)您可以使用聚合方法aggregate()进行更多自定义:

    - 例如:

    • $match查询查询条件
    • $addFields 添加或格式化现有属性
    • $filter 和 $map 我在 2) 中已经解释过
    db.collection.aggregate([
      { "$match": { "Cities.CityName": "Denver" } },
      {
        "$addFields": {
          "Cities": {
            "$map": {
              "input": {
                "$filter": {
                  "input": "$Cities",
                  "cond": { "$eq": ["$$this.CityName", "Denver"] }
                }
              },
              "in": "$$this._id"
            }
          }
        }
      }
    ])
    

    Playground

    • 结果:
    [
      {
        "Cities": [
          ObjectId("6146ada531696ee91a3f5a50")
        ],
        "StateCode": "CO",
        "StateName": "Colorado",
        "_id": ObjectId("6146ada531696ee91a3f9fa4")
      }
    ]
    

    【讨论】:

    • 这正是我所需要的。谢谢你。在 t-sql 中看起来很简单,但这可能是因为我习惯于加入多个表。我敢肯定,在完成 Pluralsight / Udemy 上的几门 mongo 课程并练习之后,它看起来会很简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2023-03-21
    • 2015-11-08
    • 1970-01-01
    • 2018-03-14
    • 2015-10-01
    • 2020-06-26
    相关资源
    最近更新 更多