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

Clasificación adhesiva dinámica en Mongo para un valor o lista simple

No se puede reproducir su error, pero tiene algunos "errores tipográficos" en su pregunta, por lo que no puedo estar seguro de lo que realmente tiene.

Pero suponiendo que realmente esté trabajando con MongoDB 2.6 o superior, entonces probablemente desee el $setIntersection o $setIsSubset operadores en lugar de $setUnion . Esos operadores implican contenidos "coincidentes" de la matriz con la que se comparan, donde $setUnion simplemente combina la matriz proporcionada con la existente:

db.people.aggregate([
    { "$project": {
        "first_name": 1,
        "last_name": 1,
        "sticky": { 
            "$size": { 
                "$setIntersection": [ "$offices", [ "FL", "SC" ]] 
            }
        },
        "offices": 1
    }},
    { "$sort": {
        "sticky": -1,
        "last_name": 1
    }}
])

En versiones anteriores donde no tiene esos operadores de conjunto solo está usando $unwind para trabajar con la matriz, y el mismo tipo de $cond operación como antes dentro de un $group para volver a unirlo todo:

db.people.aggregate([
    { "$unwind": "$offices" },
    { "$group": {
        "_id": "$_id",
        "first_name": { "$first": "$first_name" },
        "last_name": { "$first": "$last_name",
        "sticky": { "$sum": { "$cond": [
            { "$or": [
                { "$eq": [ "$offices": "FL" ] },
                { "$eq": [ "$offices": "SC" ] },
            ]},
            1,
            0
        ]}},
        "offices": { "$push": "$offices" }
    }},
    { "$sort": {
        "sticky": -1,
        "last_name": 1
    }}
])

Pero ciertamente estabas en el camino correcto. Simplemente elija la operación de ajuste correcta u otro método para obtener su necesidad precisa.

O dado que ha publicado su forma de obtener lo que desea, una mejor manera de escribir ese tipo de "coincidencia ordenada" es esta:

db.people.aggregate([
    { "$project": {
        "first_name": 1,
        "last_name": 1,
        "sticky": { "$cond": [
            { "$anyElementTrue": {
                "$map": {
                    "input": "$offices",
                    "as": "o",
                    "in": { "$eq": [ "$$o", "FL" ] }
                }
            }},
            2,
            { "$cond": [
                { "$anyElementTrue": {
                    "$map": {
                        "input": "$offices",
                        "as": "o",
                        "in": { "$eq": [ "$$o", "SC" ] }
                    }
                }},
                1,
                0
            ]}
        ]},
        "offices": 1
    }},
    { "$sort": {
        "sticky": -1,
        "last_name": 1
    }}
])

Y eso le daría prioridad a los documentos con "oficinas" que contengan "FL" sobre "SC" y, por lo tanto, sobre todos los demás, y haciendo la operación dentro de un solo campo. Eso también debería ser muy fácil para las personas ver cómo abstraer eso en el formulario usando $unwind en versiones anteriores sin los operadores de conjunto. Donde simplemente proporciona el valor de "peso" más alto a los elementos que desea en la parte superior anidando $cond declaraciones.