MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

MongoDB:jak znaleźć 10 losowych dokumentów w kolekcji 100?

Odpowiedź została udzielona dawno temu i od tego czasu MongoDB znacznie się rozwinęło.

Jak opublikowano w innej odpowiedzi, MongoDB obsługuje teraz próbkowanie w ramach agregacji od wersji 3.2:

Sposób, w jaki możesz to zrobić, to:

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

Lub:

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

Istnieje jednak kilka ostrzeżeń dotyczących operatora $sample:

(stan na 6 listopada 2017 r., gdzie najnowsza wersja to 3.4) => Jeśli którykolwiek z tych warunków nie jest spełniony:

  • $samp to pierwszy etap potoku
  • N to mniej niż 5% wszystkich dokumentów w kolekcji
  • Zbiór zawiera ponad 100 dokumentów

Jeśli którykolwiek z powyższych warunków NIE jest spełniony, $sample wykonuje skanowanie kolekcji, a następnie losowe sortowanie w celu wybrania N dokumentów.

Jak w ostatnim przykładzie z $match

STARA ODPOWIEDŹ

Zawsze możesz uruchomić:

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

Ale kolejność nie będzie losowa i będziesz potrzebować dwóch zapytań (jedno zliczanie, aby uzyskać YOUR_COLLECTION_SIZE) lub oszacować jego wielkość (około 100 rekordów, około 1000, około 10000...)

Możesz również dodać pole do wszystkich dokumentów z losową liczbą i zapytaniem według tej liczby. Wadą byłoby to, że za każdym razem, gdy uruchomisz to samo zapytanie, otrzymasz te same wyniki. Aby to naprawić, zawsze możesz grać z limitem i pomijać lub nawet sortować. równie dobrze możesz aktualizować te liczby losowe za każdym razem, gdy pobierasz rekord (co oznacza więcej zapytań).

--Nie wiem, czy używasz Mongoose, Mondoid czy bezpośrednio Mongo Driver dla konkretnego języka, więc napiszę wszystko o powłoce Mongo.

Tak więc, powiedzmy, rekord produktu będzie wyglądał tak:

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

i proponuję użyć:

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

Wtedy możesz zrobić:

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

wtedy możesz uruchamiać okresowo, aby okresowo aktualizować pole _random_sample dokumentu:

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)

lub po prostu za każdym razem, gdy pobierasz jakieś rekordy, możesz zaktualizować je wszystkie lub tylko kilka (w zależności od tego, ile rekordów pobrałeś)

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

EDYTUJ

Należy pamiętać, że

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

nie będzie działać zbyt dobrze, ponieważ zaktualizuje wszystkie produkty pasujące do zapytania z takim samym Liczba losowa. Ostatnie podejście działa lepiej (aktualizacja niektórych dokumentów podczas ich pobierania)



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Połącz dwa zapytania OR z operatorem AND w Mongoose

  2. Czy bazy danych zorientowane na dokumenty mają zastąpić relacyjne bazy danych?

  3. Jak agregować według daty, gdy w ramach agregacji podany jest pełny znacznik czasu?

  4. Mając listę identyfikatorów, jaki jest najlepszy sposób na sprawdzenie, które identyfikatory nie istnieją w kolekcji?

  5. Uzyskiwanie wyniku $grupy z liczbą grup