sql >> Base de Datos >  >> NoSQL >> MongoDB

Búsqueda de matriz anidada múltiple de Mongodb

Necesita el .aggregate() método para "filtrar" cualquier contenido de matriz para más de una coincidencia singular, y también la coincidencia básica es mucho más simple ya que a MongoDB no le importa que los datos estén dentro de las matrices, siempre que la ruta especificada sea correcta:

db.collection.aggregate([
    { "$match": { "data.userid": 1 } },
    { "$project": {
        "data": {
            "$setDifference": [
                { "$map": {
                    "input": "$data",
                    "as": "el",
                    "in": { 
                        "$cond": [
                            { "$setIsSubset": [ [1], "$$el.userid" ] },
                            "$$el",
                            false
                        ]
                    }
                }},
                [false]
            ]
        }
    }},
    { "$match": { "data.0": { "$exists": true } }}
])

Con PHP esto se anota de la siguiente manera:

$collection->aggregate(array(
    array( '$match' => array( "data.userid" => 1 )),
    array(
        '$project' => array(
            'data' => array(
                '$setDifference' => array(
                    array(
                        '$map' => array(
                            'input' => '$data',
                            'as' => 'el',
                            'in' => array(
                                '$cond' => array(
                                    array( '$setIsSubset' => array(array(1),'$$el.userid') ),
                                    '$$el',
                                    FALSE
                                )
                            )
                        )
                    ),
                    array(FALSE)
                )
            )
        )
    ),
    array( '$match' => array( 'data.0' => array( '$exists' => TRUE ) ) )
))

El $map El operador permite la inspección de cada elemento de la matriz externa y pasa cada elemento al $cond operación ternaria. Esto procesa un $setIsSubset operación en la matriz "interna" para ver si de hecho contiene uno de los valores en el conjunto alternativo (en este caso [1] ) y donde un true se realiza la evaluación, luego se devuelve el elemento o de lo contrario false .

El punto de $setDifference es eliminar esos false valores de la matriz modificada y solo devuelve elementos coincidentes. Y finalmente el $exists la prueba busca ver que la matriz externa en realidad tiene al menos un elemento y no está vacía como resultado del filtrado.

Los documentos devueltos son los que tienen la condición coincidente y solo los elementos de la matriz que también coinciden con la condición especificada.

Por supuesto, los operadores aquí requieren que tenga al menos MongoDB 2.6 como servidor (que ahora es una versión bastante antigua y al menos una actualización recomendada), pero si todavía tiene una versión menor, entonces necesita un enfoque tradicional con $unwind y $group :

$collection->aggregate(array(
    array( '$match' => array( "data.userid" => 1 )),
    array( '$unwind' => '$data' ),
    array( '$match' => array( 'data.userid' => 1 )),
    array( 
        '$group' => array(
            '_id' => '$_id',
            'data' => array( '$push' => '$data' )
        )
    )
))