web-dev-qa-db-fra.com

Comment obtenir toutes les valeurs qui contiennent une partie d'une chaîne en utilisant la recherche de mangouste?

J'ai le problème suivant lors de la récupération des données de MongoDB à l'aide de mangouste.

Voici mon schéma:

const BookSchema = new Schema(
    {
        _id:Number,
        title:String,
        authors:[String],
        subjects:[String]   
    }
);

comme vous pouvez le voir, j'ai 2 tableaux intégrés dans l'objet, disons que le contenu des auteurs peut être quelque chose comme ceci: auteurs: ["Alex Ferguson", "Didier Drogba", "Cristiano Ronaldo", "Alex"]
ce que j'essaie de réaliser, c'est de mettre tous les Alex dans le tableau.

Jusqu'à présent, j'ai pu obtenir les valeurs si elles correspondent complètement à la valeur. Cependant, si j'essaie d'obtenir ceux contenant Alex, la réponse est toujours [].

Ce que je veux savoir, c'est comment je peux le faire en utilisant find () sans effectuer de réduction de carte pour créer une vue ou une collection, puis en appliquant find () par-dessus.

Le code fonctionne ici pour des correspondances exactes

Book.find( {authors:req.query.q} , function(errs, books){
            if(errs){
                res.send(errs); 
            }

            res.json(books);
        });

J'ai essayé certaines choses mais pas de chance {auteurs: {$ elemMatch: req.query.q}} {auteurs: {$ in: [req.query.q]}}

Celui-ci me donne une erreur et en plus de cela dit est très inefficace dans un autre post que j'ai trouvé ici. {$ où: this.authors.indexOf (req.query.q)! = -1}

et j'ai aussi essayé {author: {$ regex: "./value/i"}}

La réduction de la carte fonctionne bien, je dois la faire fonctionner en utilisant l'autre approche pour voir laquelle est la meilleure?

Toute aide est grandement appréciée. Je suis sûr que c'est facile, mais je suis nouveau avec NodeJS et Mongo et je n'ai pas pu le découvrir par moi-même.

30
Dyan

Vous avez presque répondu à cela vous-même dans vos balises. MongoDB a un ($regex opérateur qui permet de soumettre une expression régulière sous forme de requête. Donc, vous recherchez des chaînes contenant "Alex", vous procédez comme suit:

Books.find(
    { "authors": { "$regex": "Alex", "$options": "i" } },
    function(err,docs) { 
    } 
);

Vous pouvez également le faire:

Books.find(
    { "authors": /Alex/i }, 
    function(err,docs) { 

    }
);

Les deux sont valides et différents de la façon dont vous avez essayé dans la syntaxe prise en charge correcte, comme indiqué dans la documentation.

Mais bien sûr, si vous demandez réellement "comment obtenir les résultats du" tableau "uniquement pour ceux qui correspondent à" Alex "quelque part dans la chaîne?" alors c'est un peu différent.

Correspondance complexe pour plus de un élément de tableau est le domaine du framework d'agrégation (ou éventuellement mapReduce, mais c'est beaucoup plus lent ), où vous devez "filtrer" le contenu du tableau.

Vous commencez à peu près la même chose. La clé ici est de $unwind pour "dénormaliser" le contenu du tableau afin de pouvoir "filtrer" correctement les documents individuels. Reconstruisez ensuite le tableau avec les documents "correspondants".

Books.aggregate(
    [
        // Match first to reduce documents to those where the array contains the match
        { "$match": {
            "authors": { "$regex": "Alex", "$options": i }
        }},

        // Unwind to "de-normalize" the document per array element
        { "$unwind": "$authors" },

        // Now filter those document for the elements that match
        { "$match": {
            "authors": { "$regex": "Alex", "$options": i }
        }},

        // Group back as an array with only the matching elements
        { "$group": {
            "_id": "$_id",
            "title": { "$first": "$title" },
            "authors": { "$Push": "$authors" },
            "subjects": { "$first": "$subjects" }
        }}
    ],
    function(err,results) {

    }
)
88
Neil Lunn