Zoek document met array dat een specifieke waarde bevat

Als ik dit schema heb…

person = {
    name : String,
    favoriteFoods : Array
}

… waar de favoriteFoodsarray is gevuld met strings. Hoe kan ik met mangoest alle personen vinden die “sushi” als hun favoriete eten hebben?

Ik hoopte op iets in de trant van:

PersonModel.find({ favoriteFoods : { $contains : "sushi" }, function(...) {...});

(Ik weet dat er geen $containsin mongodb is, ik leg alleen uit wat ik verwachtte te vinden voordat ik de oplossing kende)


Antwoord 1, autoriteit 100%

Omdat favouriteFoodseen eenvoudige reeks tekenreeksen is, kunt u dat veld gewoon rechtstreeks opvragen:

PersonModel.find({ favouriteFoods: "sushi" }, ...); // favouriteFoods contains "sushi"

Maar ik zou ook aanraden om de string-array expliciet te maken in je schema:

person = {
    name : String,
    favouriteFoods : [String]
}

De relevante documentatie is hier te vinden: https://docs.mongodb.com /manual/tutorial/query-arrays/


Antwoord 2, autoriteit 23%

Er is geen operator $containsin mongodb.

Je kunt het antwoord van JohnnyHK gebruiken, want dat werkt. De analogie die het dichtst in de buurt komt van de bevat die mongo heeft, is $in. Als u dit gebruikt, ziet uw zoekopdracht er als volgt uit:

PersonModel.find({ favouriteFoods: { "$in" : ["sushi"]} }, ...);

Antwoord 3, autoriteit 15%

Ik denk dat $allin deze situatie geschikter zou zijn. Als je op zoek bent naar een persoon die van sushi houdt, dan doe je:

PersonModel.find({ favoriteFood : { $all : ["sushi"] }, ...})

Omdat u uw zoekopdracht misschien meer wilt filteren, kunt u dit als volgt doen:

PersonModel.find({ favoriteFood : { $all : ["sushi", "bananas"] }, ...})

$inis zoals OR en $allzoals AND. Controleer dit: https://docs.mongodb.com/manual/reference/operator /query/all/


Antwoord 4, autoriteit 12%

In het geval dat de array objecten bevat, bijvoorbeeld als favouriteFoodseen array is van objecten van het volgende:

{
  name: 'Sushi',
  type: 'Japanese'
}

u kunt de volgende zoekopdracht gebruiken:

PersonModel.find({"favouriteFoods.name": "Sushi"});

Antwoord 5, autoriteit 4%

In het geval dat u documenten moet vinden die NULL-elementen bevatten in een reeks subdocumenten, heb ik deze query gevonden die redelijk goed werkt:

db.collection.find({"keyWithArray":{$elemMatch:{"$in":[null], "$exists":true}}})

Deze zoekopdracht is afkomstig uit dit bericht: MongoDb-query-array met null-waarden

Het was een geweldige vondst en het werkt veel beter dan mijn eigen initiële en verkeerdeversie (die alleen goed bleek te werken voor arrays met één element):

.find({
    'MyArrayOfSubDocuments': { $not: { $size: 0 } },
    'MyArrayOfSubDocuments._id': { $exists: false }
})

Antwoord 6

In het geval van lookup_food_array is array.

match_stage["favoriteFoods"] = {'$elemMatch': {'$in': lookup_food_array}}

In het geval dat lookup_food_array een string is.

match_stage["favoriteFoods"] = {'$elemMatch': lookup_food_string}

Antwoord 7

Hoewel akkoord gaan met find() het meest effectief is in uw gebruik. Er is nog steeds een $match of aggregation-framework, om het opvragen van een groot aantal items te vergemakkelijken en een laag aantal resultaten te genereren die waardevol voor u zijn, vooral voor het groeperen en maken van nieuwe bestanden.

 PersonModel.aggregate([
            { 
                 "$match": { 
                     $and : [{ 'favouriteFoods' : { $exists: true, $in: [ 'sushi']}}, ........ ]  }
             },
             { $project : {"_id": 0, "name" : 1} }
            ]);

Antwoord 8

Voor Loopback3 werkten alle gegeven voorbeelden niet voor mij, of toch zo snel als het gebruik van REST API. Maar het hielp me om het exacte antwoord te vinden dat ik nodig had.

{"where":{"arrayAttribute":{ "all" :[String]}}}


Antwoord 9

Met vul& $indeze code zal nuttig zijn.

ServiceCategory.find().populate({
    path: "services",
    match: { zipCodes: {$in: "10400"}},
    populate: [
        {
            path: "offers",
        },
    ],
});

Antwoord 10

Er zijn enkele manieren om dit te bereiken. De eerste is door de operator $elemMatch:

const docs = await Documents.find({category: { $elemMatch: {$eq: 'yourCategory'} }});
// you may need to convert 'yourCategory' to ObjectId

De tweede is door $inof $alloperators:

const docs = await Documents.find({category: { $in: [yourCategory] }});

of

const docs = await Documents.find({category: { $all: [yourCategory] }});
// you can give more categories with these two approaches 
//and again you may need to convert yourCategory to ObjectId

$inis zoals OR en $allzoals AND. Raadpleeg deze link voor meer informatie: https://docs.mongodb.com/ handleiding/referentie/operator/query/all/

Derde is door de functie aggregate():

const docs = await Documents.aggregate([
    { $unwind: '$category' },
    { $match: { 'category': mongoose.Types.ObjectId(yourCategory) } }
]};

met aggregaat() krijgt u slechts één categorie-ID in uw categoriearray.

Ik krijg deze codefragmenten van mijn projecten waar ik documenten met specifieke categorie/categorieën moest vinden, dus je kunt het gemakkelijk aanpassen aan je behoeften.


Antwoord 11

Als je zoiets als een “bevat”-operator wilt gebruiken via javascript, kun je daar altijd een reguliere expressie voor gebruiken…

bijv.
Stel dat u een klant wilt ophalen met “Bartolomew” als naam

async function getBartolomew() {
    const custStartWith_Bart = await Customers.find({name: /^Bart/ }); // Starts with Bart
    const custEndWith_lomew = await Customers.find({name: /lomew$/ }); // Ends with lomew
    const custContains_rtol = await Customers.find({name: /.*rtol.*/ }); // Contains rtol
    console.log(custStartWith_Bart);
    console.log(custEndWith_lomew);
    console.log(custContains_rtol);
}

Antwoord 12

Ik weet dat dit onderwerp oud is, maar voor toekomstige mensen die zich dezelfde vraag zouden kunnen stellen, zou een andere ongelooflijk inefficiënte oplossing kunnen zijn:

PersonModel.find({$where : 'this.favouriteFoods.indexOf("sushi") != -1'});

Dit vermijdt alle optimalisaties door MongoDB, dus gebruik het niet in productiecode.

Other episodes