sql >> Database teknologi >  >> NoSQL >> MongoDB

MongoDB:hvordan finder man 10 tilfældige dokumenter i en samling på 100?

Dette blev besvaret for længe siden, og siden da har MongoDB udviklet sig meget.

Som skrevet i et andet svar, understøtter MongoDB nu sampling inden for Aggregation Framework siden version 3.2:

Måden du kan gøre dette på er:

db.products.aggregate([{$sample: {size: 5}}]); // You want to get 5 docs

Eller:

db.products.aggregate([
  {$match: {category:"Electronic Devices"}}, // filter the results
  {$sample: {size: 5}} // You want to get 5 docs
]);

Der er dog nogle advarsler om $sample-operatøren:

(fra 6. november 2017, hvor seneste version er 3.4) => Hvis noget af dette ikke er opfyldt:

  • $sample er den første fase af pipelinen
  • N er mindre end 5 % af de samlede dokumenter i samlingen
  • Samlingen indeholder mere end 100 dokumenter

Hvis nogen af ​​ovenstående betingelser IKKE er opfyldt, udfører $sample en samlingsscanning efterfulgt af en tilfældig sortering for at vælge N dokumenter.

Som i det sidste eksempel med $match

GAMMEL SVAR

Du kan altid køre:

db.products.find({category:"Electronic Devices"}).skip(Math.random()*YOUR_COLLECTION_SIZE)

Men rækkefølgen vil ikke være tilfældig, og du skal bruge to forespørgsler (et antal for at få YOUR_COLLECTION_SIZE) eller anslå, hvor stor den er (det er omkring 100 poster, omkring 1000, omkring 10.000...)

Du kan også tilføje et felt til alle dokumenter med et tilfældigt tal og forespørge efter det nummer. Ulempen her ville være, at du vil få de samme resultater, hver gang du kører den samme forespørgsel. For at rette op på det kan du altid spille med limit og spring eller endda med sortering. du kan lige så godt opdatere disse tilfældige tal, hver gang du henter en post (indebærer flere forespørgsler).

--Jeg ved ikke, om du bruger Mongoose, Mondoid eller direkte Mongo Driver til et bestemt sprog, så jeg vil skrive alt om mongo shell.

Din, lad os sige, produktregistrering ville således se sådan ud:

{
 _id: ObjectId("..."),
 name: "Awesome Product",
 category: "Electronic Devices",
}

og jeg vil foreslå at bruge:

{
 _id: ObjectId("..."),
 name: "Awesome Product",
 category: "Electronic Devices",
 _random_sample: Math.random()
}

Så kunne du gøre:

db.products.find({category:"Electronic Devices",_random_sample:{$gte:Math.random()}})

så kan du køre med jævne mellemrum, så du opdaterer dokumentets _random_sample felt med jævne mellemrum:

var your_query = {} //it would impact in your performance if there are a lot of records
your_query = {category: "Electronic Devices"} //Update 
//upsert = false, multi = true
db.products.update(your_query,{$set:{_random_sample::Math.random()}},false,true)

eller bare når du henter nogle poster, kan du opdatere dem alle eller kun nogle få (afhængigt af hvor mange poster du har hentet)

for(var i = 0; i < records.length; i++){
   var query = {_id: records[i]._id};
   //upsert = false, multi = false
   db.products.update(query,{$set:{_random_sample::Math.random()}},false,false);
}

REDIGER

Vær opmærksom på, at

db.products.update(your_query,{$set:{_random_sample::Math.random()}},false,true)

vil ikke fungere særlig godt, da det vil opdatere alle produkter, der matcher din forespørgsel med det samme tilfældigt tal. Den sidste fremgangsmåde fungerer bedre (opdatering af nogle dokumenter, efterhånden som du henter dem)



  1. Vælg indlejrede felter i mongo db

  2. SignalR kan ikke oprette forbindelse til Azure Redis på SSL

  3. Måder at implementere dataversionering i MongoDB

  4. Hvordan $set Update Operator fungerer i MongoDB