sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB:hur hittar man 10 slumpmässiga dokument i en samling av 100?

Detta besvarades för länge sedan och sedan dess har MongoDB utvecklats kraftigt.

Som postat i ett annat svar, stöder MongoDB nu sampling inom Aggregation Framework sedan version 3.2:

Så här kan du göra detta:

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
]);

Det finns dock några varningar om $sample-operatorn:

(från och med den 6 november 2017, där senaste versionen är 3.4) => Om något av detta inte uppfylls:

  • $sample är det första steget i pipelinen
  • N är mindre än 5 % av de totala dokumenten i samlingen
  • Samlingen innehåller mer än 100 dokument

Om något av ovanstående villkor INTE uppfylls, utför $sample en samlingsskanning följt av en slumpmässig sortering för att välja N dokument.

Som i det sista exemplet med $match

GAMMEL SVAR

Du kan alltid köra:

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

Men beställningen kommer inte att vara slumpmässig och du behöver två frågor (en räkning för att få YOUR_COLLECTION_SIZE) eller uppskatta hur stor den är (det är cirka 100 poster, cirka 1000, cirka 10000...)

Du kan också lägga till ett fält i alla dokument med ett slumpmässigt nummer och fråga efter det numret. Nackdelen här skulle vara att du får samma resultat varje gång du kör samma fråga. För att fixa det kan du alltid spela med limit och skip eller till och med sortera. du kan lika gärna uppdatera de slumpmässiga siffrorna varje gång du hämtar en post (medför fler frågor).

--Jag vet inte om du använder Mongoose, Mondoid eller direkt Mongo Driver för något specifikt språk, så jag kommer att skriva allt om mongo shell.

Därför skulle din, låt oss säga, produktpost se ut så här:

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

och jag skulle föreslå att du använder:

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

Då kan du göra:

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

sedan kan du köra regelbundet så att du uppdaterar dokumentets _random_sample-fält med jämna mellanrum:

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 precis när du hämtar några poster kan du uppdatera dem alla eller bara några (beroende på hur många poster du har hämtat)

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);
}

REDIGERA

Var medveten om att

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

kommer inte att fungera särskilt bra eftersom det uppdaterar alla produkter som matchar din fråga med samma slumpmässigt nummer. Det sista tillvägagångssättet fungerar bättre (uppdatering av vissa dokument när du hämtar dem)



  1. Arbetar med @cache_page() dekoratör i django-redis-cache

  2. Hur ignorerar man nollor samtidigt som man tar upp ett MongoDB-dokument?

  3. Importera data till dina nyskapade MongoDB-instanser

  4. Undvik sammanlagd 16MB-gräns