MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB trouve un sous-document et trie les résultats

Comme indiqué, j'espère que vos documents ont réellement un tableau, mais si $elemMatch fonctionne pour vous, ils devraient le faire.

Dans tous les cas, vous ne pouvez pas trier par élément dans un tableau à l'aide de find. Mais il existe un cas où vous pouvez le faire en utilisant .aggregate() :

db.collection.aggregate([

    // Match the documents that you want, containing the array
    { "$match": {
        "nlp.entities": {
            "$elemMatch": { 
                "text": "Neelie Kroes", 
                "type": "Person"   
            }
        }
    }},

    // Project to "store" the whole document for later, duplicating the array
    { "$project": {
        "_id": {
            "_id": "$_id",
            "url": "$url",
            "nlp": "$nlp"          
        },
        "entities": "$nlp.entities"
    }},

    // Unwind the array to de-normalize
    { "$unwind": "$entities" },

    // Match "only" the relevant entities
    { "$match": {
        "entities.text": "Neelie Kroes", 
        "entities.type": "Person"   
    }},

    // Sort on the relevance
    { "$sort": { "entities.relevance": -1 } },

    // Restore the original document form
    { "$project": {
        "_id": "$_id._id",
        "url": "$_id.url",
        "nlp": "$_id.nlp"
    }}
])

Donc, essentiellement, après avoir fait le $match condition pour les documents contenant la correspondance pertinente, vous utilisez ensuite $project "stocker" le document d'origine dans le _id champ et $unwind une "copie" du tableau "entités".

Le prochain $match "filtre" le contenu du tableau uniquement à ceux qui sont pertinents. Ensuite, vous appliquez le $sort aux documents "correspondants".

Comme le document "original" était stocké sous _id , vous utilisez $project pour "restaurer" la structure avec laquelle le document devait réellement commencer.

C'est ainsi que vous "triez" sur votre élément correspondant d'un tableau.

Notez que si vous avez plusieurs "correspondances" dans un tableau pour un document parent, vous devrez alors utiliser un $group pour obtenir la valeur $max du champ "pertinence" afin de terminer votre tri.