MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como classificar por 'valor' de uma chave específica dentro de uma propriedade armazenada como uma matriz com pares k-v no mongodb


Supondo que o que você deseja sejam todos os documentos que tenham o valor "pontos" como uma "chave" na matriz e, em seguida, classifique o "valor" para essa "chave", isso está um pouco fora do escopo do .find() método.

Razão é se você fez algo assim
db.collection.find({
    "setid": 154421, "data.k": "point" }
).sort({ "data.v" : -1 })

O problema é que mesmo que os elementos correspondentes fazem tem a chave correspondente de "ponto", não há como dizer qual data.v você está se referindo para o tipo. Além disso, um sort dentro de .find() resultados não farão algo assim:
db.collection.find({
    "setid": 154421, "data.k": "point" }
).sort({ "data.$.v" : -1 })

O que seria tentar para usar um operador posicional dentro de uma classificação, essencialmente informando qual elemento usar o valor de v sobre. Mas isso não é suportado e provavelmente não será, e para a explicação mais provável, esse valor de "índice" provavelmente seria diferente em cada documento.

Mas esse tipo de seletivo a classificação pode ser feita com o uso de .aggregate() .
db.collection.aggregate([

    // Actually shouldn't need the setid
    { "$match": { "data": {"$elemMatch": { "k": "points" } } } },

    // Saving the original document before you filter
    { "$project": {
        "doc": {
           "_id": "$_id",
           "setid": "$setid",
           "date": "$date",
           "version": "$version",
           "data": "$data"
        },
        "data": "$data"
    }}

    // Unwind the array
    { "$unwind": "$data" },

    // Match the "points" entries, so filtering to only these
    { "$match": { "data.k": "points" } },

    // Sort on the value, presuming you want the highest
    { "$sort": { "data.v": -1 } },

    // Restore the document
    { "$project": {
        "setid": "$doc.setid",
        "date": "$doc.date",
        "version": "$doc.version",
        "data": "$doc.data"
    }} 

])

É claro que isso pressupõe os data array tem apenas o um elemento que tem os pontos-chave. Se houvesse mais de um, você precisaria $group antes do tipo assim:
    // Group to remove the duplicates and get highest
    { "$group": { 
        "_id": "$doc",
        "value": { "$max": "$data.v" }
    }},

    // Sort on the value
    { "$sort": { "value": -1 } },

    // Restore the document
    { "$project": { 
        "_id": "$_id._id",
        "setid": "$_id.setid",
        "date": "$_id.date",
        "version": "$_id.version",
        "data": "$_id.data"
    }}

Portanto, há um uso de .aggregate() para fazer alguns complexos classificação em documentos e ainda retornar o resultado do documento original na íntegra.

Leia mais sobre operadores de agregação e o quadro geral. É uma ferramenta útil para aprender que leva você além de .find() .