Mongodb: Consulta el tamaño de las matrices anidadas

0

Pregunta

Tengo el siguiente Esquema:

Schema({
caller_address: {
    type: String,
    required: true,
},
traces: [[{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Call',
}]]

});

Y me gustaría recuperar sólo los objetos que tienen trazas con las Llamadas cantidad más grande que un número especificado. En otras palabras, el tamaño de al menos una matriz anidada de las huellas debe ser más grande que un número especificado. Estoy tratando de utilizar $elemMatch y $tamaño, pero sin éxito. Por ahora, tengo este código:

CallerTraces.find({ 'traces' : { $elemMatch: { $size : { $gt: minTraceSize } }}})

Donde minTraceSize es un int.

Ustedes podrían ayudarme? Lo agradecería muchísimo!

arrays mongodb nested
2021-11-23 20:27:28
1

Mejor respuesta

0

Gracias por los datos de la muestra. Mi respuesta va a ser un raw MQS solución, no una mangosta solución, por lo que algunos de traducción será necesario.

Yo era capaz de insertar dos documentos en base a tus comentarios en tu post. He tenido que cambiar el id de objeto de uno de los dos documentos de muestra debido a que las muestras tenían el mismo valor de clave principal y fue la generación de una clave duplicada excepción.

Insertar Datos De Ejemplo

db.CallerTraces.insert(
{
  "_id": ObjectId("6175e7ecc62cff004462d4a6"),
  "traces": [
    [
      ObjectId("6175e7ecc62cff004462d4a4")
    ]
  ],
  "caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990"
})


db.CallerTraces.insert(
{
  "_id": ObjectId("6175e7ecc62cff004462d4a7"),
  "traces": [
    [
      ObjectId("6175e7ecc62cff004462d4a4"),
      ObjectId("6175e7ecc62cff004462d4a4")
    ],
    [
      ObjectId("6175e7ecc62cff004462d4a4")
    ]
  ],
  "caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990"
})

Si quiero encontrar registros de tener más de 0 elementos de la matriz traces Me puede emitir el siguiente:

Encontrar más que cero rastros

db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 0 ] } })

Esto devuelve el siguiente:

Enterprise replSet [primary] barrydb> db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 0 ] } })
[
  {
    _id: ObjectId("6175e7ecc62cff004462d4a6"),
    traces: [ [ ObjectId("6175e7ecc62cff004462d4a4") ] ],
    caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
  },
  {
    _id: ObjectId("6175e7ecc62cff004462d4a7"),
    traces: [
      [
        ObjectId("6175e7ecc62cff004462d4a4"),
        ObjectId("6175e7ecc62cff004462d4a4")
      ],
      [ ObjectId("6175e7ecc62cff004462d4a4") ]
    ],
    caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
  }
]

Encuentra más de 1 traza

Si, en cambio, quiero encontrar a más de una traza, yo simplemente modificar la consulta ligeramente:

db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 1 ] } })

... y esta devuelve con los siguientes resultados:

Enterprise replSet [primary] barrydb> db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 1 ] } })
[
  {
    _id: ObjectId("6175e7ecc62cff004462d4a7"),
    traces: [
      [
        ObjectId("6175e7ecc62cff004462d4a4"),
        ObjectId("6175e7ecc62cff004462d4a4")
      ],
      [ ObjectId("6175e7ecc62cff004462d4a4") ]
    ],
    caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
  }
]

Conclusión

Cuando se intenta evaluar la longitud de la matriz en el procesador de consultas debemos elegir utilizar el $eval opción como la sintaxis para MQS no considera el caso de uso. El $eval es algo de cajón de sastre opción para las cosas que no encajan muy bien en la MQS marco.

ACTUALIZACIÓN #1 OP introducido requisitos adicionales. En lugar de buscar en el recuento de la matriz, se debe considerar el recuento de la matriz dentro de la matriz (nested interior de la matriz). Desde el método find() con el $expr pueden evaluar las matrices anidadas en vez de eso debemos utilizar el marco de agregación y descansar el exterior de la matriz. En este ejemplo se almacena la forma original en un nuevo campo llamado original a continuación, reemplaza la raíz después de todo se completa la evaluación. Desde desenrollado puede resultar en duplicados en la canalización de finalizar con un $grupo para suprimir los duplicados.

Solución

db.CallerTraces.aggregate([
    {
        $addFields: {
            "original._id": "$_id",
            "original.traces": "$traces",
            "original.caller_address": "$caller_address"
        }
    },
    {
        $unwind: "$traces"
    },
    {
        $match: { $expr: { $gt: [ { $size: "$traces" }, 1 ] } }
    },
    {
        $replaceRoot: { newRoot: "$original" }
    },
    {
        $group:
        {
            _id: "$_id",
            traces: { "$first": "$traces" },
            caller_address: { "$first": "$caller_address" }
        }
    }
])
2021-11-24 21:42:44

Hola, Gracias por tu rápida respuesta! Pero no es todavía el problema... quiero llegar a los Rastros tamaños en el segundo nivel de anidamiento. Así que, si tengo: { "_id": ObjectId("6175e7ecc62cff004462d4a7"), "huellas": [ [ ObjectId("6175e7ecc62cff004462d4a4"), ObjectId("6175e7ecc62cff004462d4a4") ] ], "caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990" }) Este objeto debe devolver cuando me puse a 2 a la minTraceSize variable.
Bruno Medeiros

@BrunoMedeiros - por favor, ver las actualizaciones en mi post.
barrypicker

funcionó! Muchas gracias! =)
Bruno Medeiros

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................