2011-06-12 10 views
9

Tengo una colección MongoDB con ~ 4M elementos.Seleccionando cada elemento Nth de una gran colección de MongoDB con PHP?

Quiero obtener X cantidad de esos elementos, espaciados uniformemente a través de toda la colección.

Por ej., Obtenga 1000 elementos de la colección, uno cada 4000 filas.

En este momento, obtengo toda la colección en un cursor y luego solo escribo cada enésimo elemento. Esto me da lo que necesito, pero la carga original de la gran colección lleva mucho tiempo.

¿Hay una manera fácil de hacer esto? En este momento mi enfoque adivinado es hacer una consulta JS en una propiedad de índice incrementado, con un módulo. Una aplicación PHP de esta:

db.collection.find({i:{$mod:[10000,0]}})

Pero esto parece que probablemente pueden tomar mucho tiempo para que la consulta se ejecute.

Jer

+0

¿Encontró alguna solución? –

Respuesta

0

Creo que el problema principal, es que la colección puede ser distribuido a través de servidores y por lo tanto hay que iterar sobre toda la colección.

+0

En este caso estoy ejecutando todo en un servidor local. – blprnt

0

No coloque todo el conjunto de datos en un cursor. Como el orden de las filas no es importante, simplemente recolecte x filas aleatorias de su total, devuelva eso como resultado y luego modifique esos registros

+0

El problema es que necesito elementos distribuidos uniformemente de mi colección, es decir, cada 1000 elemento. – blprnt

+0

Cree un campo de conteo, luego use Mapa para filtrar cada elemento enésimo, luego Redúcelo para operar en ese registro –

+0

Gracias ... le dará una oportunidad. Ya tengo un campo de conteo en su lugar. Solo hay que tratar de hacer que las cabezas/colas del mapa reduzcan la documentación. – blprnt

0

Personalmente, diseñaría en un valor "módulo", lo rellenaría con algo que sea una función representante de los datos, por lo tanto, si sus datos se insertaron a intervalos regulares a lo largo del día, podría hacer un módulo del tiempo; si no hay nada predecible, entonces podría usar un valor aleatorio; con una colección de ese tamaño, tenderá a una distribución uniforme con bastante rapidez.

Un ejemplo utilizando un valor aleatorio ...

// add the index 
    db.example.ensureIndex({modulus: 1}); 
    // insert a load of data 
    db.example.insert({ your: 'data', modulus: Math.round((Math.random() * 1000) % 1000) }); 
    // Get a 1/1000 of the set 
    db.example.find({modulus: 1}); 
    // Get 1/3 of the set 
    db.example.find({modulus: { $gt: 0, $lt: 333 }}); 
-4

Si tan sólo sus datos estaba en una base de datos SQL, como debe ser, ... esta pregunta no sería en PHP y la respuesta sería sea ​​tan fácil y rápido ...

Cargar cualquier cosa en un cursor en lugar de calcular la información directamente en el archivo db es definitivamente una mala idea, ¿no es posible hacerlo directamente en la función de MongoDB?

+0

esta respuesta es tan retrospectiva – jtromans

+0

Cuando maneja solo elementos de 4M y realiza operaciones que no son nativas de MongoDB, debe utilizar PostgreSQL. –

+0

¿Por qué?¿Por qué PostgreSQL sería mejor aquí? Soy un gran usuario de las bases de datos SQL, pero este tipo de consulta es mala para la mayoría de las bases de datos. Además, "MongoDB thingy"? No parece que realmente sepas de qué estás hablando con MongoDB para tener autoridad aquí. Ni siquiera estoy seguro de lo que quieres decir con la segunda parte de tu respuesta. – Sammaye

0

¿No sería este un caso de uso perfecto para un trabajo de reducción de mapas?

+0

Disculpas por ser gruesa pero algún código meta/código real que indique cómo se podría hacer esto sería muy apreciado. Gracias. –

+2

-1 por no responder la pregunta, esto debería ser un comentario – y3sh

0

Una forma simple (ineficaz) de hacer esto es con una transmisión.

var stream = collection.find({}).stream(); 
var counter = 0; 

stream.on("data", function (document) { 
    counter++; 

    if (counter % 10000 == 0) { 
    console.log(JSON.stringify(document, null, 2)); 
    //do something every 10,000th time 
    } 
}); 
Cuestiones relacionadas