2012-09-30 14 views
6

Mam kolekcję mongo z dokumentami. W każdym dokumencie znajduje się jedno pole, które wynosi 0 LUB 1. Potrzebuję losowej próbki 1000 rekordów z bazy danych i policz liczbę dokumentów, które mają to pole jako 1. Muszę wykonać to próbkowanie 1000 razy. Jak mam to zrobić ?Losowe pobieranie próbek z Mongo

+1

Czy możesz zaakceptować odpowiedź? –

+0

możliwy duplikat [Losowy rekord z MongoDB] (http://stackoverflow.com/questions/2824157/random-record-from-mongodb) –

+0

Hej Aditya, czy możesz zaakceptować odpowiedź? – dalanmiller

Odpowiedz

1

Oto przykład, w powłoce mongo .. zakładając kolekcję collname, a wartość zainteresowania thefield:

var total = db.collname.count(); 
var count = 0; 
var numSamples = 1000; 

for (i = 0; i < numSamples; i++) { 
    var random = Math.floor(Math.random()*total); 
    var doc = db.collname.find().skip(random).limit(1).next(); 
    if (doc.thefield) { 
     count += (doc.thefield == 1); 
    } 
} 
+0

To również odpowiada na jedno inne pytanie: w przeciwieństwie do SQL, MongoDB nie ma wbudowanej funkcji do tego naprawdę.Również ten pominięcie może (... może) stać się kłopotliwym dla większych losowych wartości, zależy jednak. – Sammaye

1

Chciałem zmienił mój komentarz na @Stennies odpowiedzieć z tym ale można również użyj indeksu auto-rosnącego auto-indeksu jako alternatywy, jeśli masz pominąć OGROMNE ilości rekordów (mówisz tu ogromnie).

napisałem kolejną odpowiedź na inne pytanie dużo jak ten, gdzie ktoś próbował znaleźć n-ty rekord kolekcji:

php mongodb find nth entry in collection

Druga połowa moją odpowiedź w zasadzie opisuje jedną potencjalną metodę którym mógłbyś podejść do tego problemu. Nadal trzeba pętli 1000 razy, aby uzyskać losowy wiersz oczywiście.

12

Dla wersji MongoDB 3.0 i wcześniej używam starej sztuczki z dni SQL (która, jak myślę, wykorzystuje Wikipedia dla ich funkcji losowej strony). Przechowuję losową liczbę od 0 do 1 w każdym obiekcie, który potrzebuję do randomizacji, nazwijmy to pole "r". Następnie dodajemy indeks do "r".

db.coll.ensureIndex(r: 1); 

Teraz, aby dostać losowa X obiektów, należy użyć:

var startVal = Math.random(); 
db.coll.find({r: {$gt: startVal}}).sort({r: 1}).limit(x); 

To daje przypadkowych przedmiotów w jednym zapytaniu find. W zależności od twoich potrzeb może to być przesada, ale jeśli masz zamiar robić dużo próbkowania w czasie, jest to bardzo skuteczny sposób bez obciążania twojego backendu.

+0

Świetnie! Bardzo mądry! –

+0

eleganckie rozwiązanie! –

-1

Jeśli używasz mongoingu, możesz użyć SequenceField do wygenerowania przyrostowego licznika.

class User(db.DynamicDocument): 
    counter = db.SequenceField(collection_name="user.counters") 

Następnie pobrać losową listę powiedzieć 100, wykonaj następujące czynności

def get_random_users(number_requested): 
    users_to_fetch = random.sample(range(1, User.objects.count() + 1), min(number_requested, User.objects.count())) 
    return User.objects(counter__in=users_to_fetch) 

gdzie można by nazwać

get_random_users(100)