在mongodb中搜索嵌套文档

时间:2020-06-03 07:11:34

标签: mongodb nested find aggregate

您好,我有一个与以下问题有关的集合,该集合保存了用户的联系信息,看起来像这样。

[{
  "_id": {
    "$oid": "5836b917885383034437d26b"
  },
  "Nombre": "Juan",
  "Email": "jsanzrobles@hotmail.es",
  "Edad": 34,
  "País": "España",
  "Contactos": [
    {
      "Usuario_contacto": {
        "_id": {
          "$oid": "5836b916885383034437d23d"
        },
        "Nombre": "Alejandro",
        "Email": "aamericagarzon@hotmail.es",
        "Edad": 32,
        "País": "España",
        "Tipo": "Usuario individual",
        "Apellidos": "América Garzón",
        "Teléfono": 639123123,
        "Ciudad": "Salamanca",
        "Identificador": "U-3491",
        "Información_creación": {
          "Fecha_creación": {
            "Mes": 7,
            "Día": 14,
            "Año": 2016
          },
          "Hora_creación": {
            "Hora": 5,
            "Minutos": 22,
            "Segundos": 16
          }
        }
      },
      "Fecha_alta": {
        "Mes": 10,
        "Día": 27,
        "Año": 2016
      },
      "Hora_alta": {
        "Hora": 23,
        "Minutos": 2,
        "Segundos": 31
      }
    },
    {
      "Usuario_contacto": {
        "_id": {
          "$oid": "5836b916885383034437d21f"
        },
        "Nombre": "Alfonso",
        "Email": "amartinezosorio@hotmail.es",
        "Edad": 23,
        "País": "España",
        "Tipo": "Usuario individual",
        "Apellidos": "Martínez Osorio",
        "Teléfono": 612311456,
        "Ciudad": "Bilbao",
        "Identificador": "U-3461",
        "Información_creación": {
          "Fecha_creación": {
            "Mes": 8,
            "Día": 22,
            "Año": 2016
          },
          "Hora_creación": {
            "Hora": 7,
            "Minutos": 22,
            "Segundos": 30
          }
        }
      },
      "Fecha_alta": {
        "Mes": 10,
        "Día": 27,
        "Año": 2016
      },
      "Hora_alta": {
        "Hora": 12,
        "Minutos": 7,
        "Segundos": 48
      }
    },
    {
      "Usuario_contacto": {
        "_id": {
          "$oid": "5836b916885383034437d232"
        },
        "Nombre": "Mercedes",
        "Email": "mreysordo@gmail.es",
        "Edad": 50,
        "País": "España",
        "Tipo": "Usuario individual",
        "Apellidos": "Rey Sordo",
        "Teléfono": 635456989,
        "Ciudad": "Castellón",
        "Identificador": "U-3480",
        "Información_creación": {
          "Fecha_creación": {
            "Mes": 4,
            "Día": 28,
            "Año": 2016
          },
          "Hora_creación": {
            "Hora": 15,
            "Minutos": 22,
            "Segundos": 15
          }
        }
      },
      "Fecha_alta": {
        "Mes": 10,
        "Día": 24,
        "Año": 2016
      },
      "Hora_alta": {
        "Hora": 14,
        "Minutos": 35,
        "Segundos": 26
      }
    }
  ],
  "Información_creación": {
    "Fecha_creación": {
      "Mes": 10,
      "Día": 23,
      "Año": 2016
    },
    "Hora_creación": {
      "Hora": 10,
      "Minutos": 12,
      "Segundos": 10
    }
  },
  "Apellidos": "Sanz Robles",
  "Identifier": "U-3455",
  "Tipo": "Usuario individual",
  "Teléfono": 675456789,
  "Ciudad": "Granada"
}

被要求执行的练习是为在同一城市(“城市”)具有2个或更多联系人的每个用户创建一个新文档。它必须看起来像这样

[...{
      _id : { Identifier:    ...
                  Ciudad:   ... },
      Counter:  3 
}, ...
]

我是mongo的新手,我做了很多尝试,我知道我必须创建一个聚合,但我不知道该如何过滤。

1 个答案:

答案 0 :(得分:0)

首先,我将使用简化的数据结构,因为我们只需要了解城市和文档ID。

所以我们插入一些记录:

db.test.insertMany([
   { "_id": 1, "contacts" : [
     { "name": "Name-1", "city" : "Manchester" },
     { "name": "Name-2", "city" : "Manchester" },
     { "name": "Name-3", "city" : "Manchester" }]
   },
   { "_id": 2, "contacts" : [
     { "name": "Name-4", "city" : "York" },
     { "name": "Name-5", "city" : "Manchester" },
     { "name": "Name-6", "city" : "Sheffield" }]
   },
   { "_id": 3, "contacts" : [
     { "name": "Name-7", "city" : "Sheffield" },
     { "name": "Name-8", "city" : "York" },
     { "name": "Name-9", "city" : "Sheffield" }]
   }
])

然后,我们需要一个聚集管道来展开contacts的子文档并对其重新分组,以便我们可以用$sum进行计数:

db.test.aggregate([
  { "$unwind": "$contacts" },
  { "$group": { "_id": { "_id": "$_id", "city": "$contacts.city" }, "count": { $sum: 1 } } }
]);

{ "_id" : { "_id" : 2, "city" : "Manchester" }, "count" : 1 }
{ "_id" : { "_id" : 2, "city" : "Sheffield" }, "count" : 1 }
{ "_id" : { "_id" : 3, "city" : "York" }, "count" : 1 }
{ "_id" : { "_id" : 1, "city" : "Manchester" }, "count" : 3 }
{ "_id" : { "_id" : 2, "city" : "York" }, "count" : 1 }
{ "_id" : { "_id" : 3, "city" : "Sheffield" }, "count" : 2 }

这时,我们需要过滤掉计数少于2的那些,可以通过$ match阶段将算子($gte大于或等于操作符(db.test.aggregate([ { "$unwind": "$contacts" }, { "$group": { "_id": { "_id": "$_id", "city": "$contacts.city" }, "count": { $sum: 1 } } }, { "$match" : { "count" : { "$gte" : 2 } } } ]); { "_id" : { "_id" : 1, "city" : "Manchester" }, "count" : 3 } { "_id" : { "_id" : 3, "city" : "Sheffield" }, "count" : 2 } )做到这一点:

$out

这将获得我们所需的结果,因此现在只需将它们通过管道传送到另一个集合中,就可以通过db.test.aggregate([ { "$unwind": "$contacts" }, { "$group": { "_id": { "_id": "$_id", "city": "$contacts.city" }, "count": { $sum: 1 } } }, { "$match" : { "count" : { "$gte" : 2 } } }, { "$out" : "test2" } ]); 阶段来实现:

test2

这会将所有结果输出到名为db.test2.find() { "_id" : { "_id" : 1, "city" : "Manchester" }, "count" : 3 } { "_id" : { "_id" : 3, "city" : "Sheffield" }, "count" : 2 } 的集合中,现在我们就可以直接对其进行查询。

hideUploadButton: true

以下是一些有用的链接,以了解聚合阶段的更多信息:

相关问题