首页 > 解决方案 > 文档数组的 Mongo 项目 _id

问题描述

我很难写 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。

{“城市._id”:1}

但这总是返回给我的国家文件 ID 不是匹配的城市文件 _id。

我究竟做错了什么?

标签: mongodbmongodb-compass

解决方案


1)您可以使用$(投影)$elemMatch(投影)

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

  • 例如: { "Cities.$": 1 }或​<code>{“Cities”:{“$elemMatch”:{“CityName”:“Denver”}}}

  • 结果:

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

操场

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

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

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

  • 前任:

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

操场

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

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

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

  • 前任:

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

操场

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

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"
        }
      }
    }
  }
])

操场

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

推荐阅读