Pregunta

Los objetos en la base de datos tienen una matriz de 'Propiedades', que pueden mantener objetos diversos.Algunos de ellos presentan números o rangos y se ven como:

{'value': 10}

o

{'minValue': 4, 'maxValue': 8}

Al consultar la colección para un número específico, como X, quiero encontrar todos los documentos donde cualquiera de los dos valores es igual a X o MinValue <= X <= MAXVALUE MAXVALUE.Mi primer intento de una consulta parece

db.Pool0.find({$or: [{'properties.value': X}, {'properties.minValue': {$lte: X}, 'properties.maxValue': {$gte: X}}]}, {'_id': 1}).pretty()

El inconveniente es que si la matriz de propiedades contiene múltiples objetos que especifican MinValue y MAXVALUE, X puede ser entre cualquiera de ellos.Por ejemplo

"properties" : [
    {
        "minValue" : 4,
        "maxValue" : 6
    },
    {
        "minValue" : 10,
        "maxValue" : 20
    }
]

coincidirá para x= 8. ¿Se puede mejorar la consulta para que la estructura del objeto dentro de las propiedades sea respetada?

¿Fue útil?

Solución

, básicamente, quiere usarla $elemMatch combinado con una $or condiciónEn esta forma:

db.collection.find({
    "$or": [
        {
            "properties": { "$elemMatch": {
                "minValue": { "$lte": 8 },
                "maxValue": { "$gte": 8 }
            }}
        },
        {
            "properties.value": 8
        }
    ]
})

que cubre la reunión de los documentos que contienen el rango, así como el posible nombre de la clave para el campo en las propiedades.

Pero tenga en cuenta que los documentos correspondientes son diferentes a los elementos que coinciden en una matriz.Entonces, si solo espera que se devuelvan los elementos de la matriz que coincidan y usted tiene más de uno, entonces usa el formulario agregado:

db.collection.aggregate([
    // Matching documents is still good practice
    { "$match": {
        "$or": [
             {
                 "properties": { "$elemMatch": {
                    "minValue": { "$lte": 8 },
                    "maxValue": { "$gte": 8 }
                 }}
             },
             {
                 "properties.value": 8
             }
         ]
    }},

    // Unwind to de-normalize
    { "$unwind": "$properties" },

    // Then match to filter the elements
    { "$match": {
        "$or": [
             {
                "properties.minValue": { "$lte": 8 },
                "properties.maxValue": { "$gte": 8 }
             },
             { "properties.value": 8 }
        ]
    }},

    // Reconstruct the filtered array
    { "$group": {
        "_id": "$_id",
        "properties": { "$push": "$properties" }
    }}
])

Pero si solo habrá una coincidencia de que está seguro de que simplemente use la proyección con Buscar:

db.collection.find(
    { 
        "$or": [
            {
                "properties": { "$elemMatch": {
                    "minValue": { "$lte": 8 },
                    "maxValue": { "$gte": 8 }
                }}
            },
            {
            "properties.value": 8
            }
        ]
    },
    { "properties.$": 1 }
)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top