2010-06-09 11 views
18

Tengo un almacén de datos con alrededor de 1,000,000 de entidades en un modelo. Quiero buscar 10 entidades aleatorias a partir de esto.¿Obteniendo un registro aleatorio del almacén de datos de Google App Engine?

No estoy seguro de cómo hacer esto? alguien puede ayudar?

+0

posible duplicado de [Consultando N registros aleatorios en el almacén de datos Appengine] (http://stackoverflow.com/questions/1105004/querying-for-n-random-records-on-appengine-datastore) –

Respuesta

21

Asigne a cada entidad un número aleatorio y guárdelo en la entidad. A continuación, busque diez registros cuyo número aleatorio sea mayor que (o menor que) algún otro número aleatorio.

Esto no es totalmente aleatorio, sin embargo, dado que las entidades con números aleatorios cercanos tenderán a aparecer juntas. Si quieres superar esto, haz diez consultas basadas en diez números aleatorios, pero esto será menos eficiente.

+0

Exactamente a la derecha. Podría querer mencionar el rango (0..1 es estándar) para los números aleatorios. –

+4

Una posibilidad de aumentar la aleatoriedad sin dañar la eficiencia del tiempo de lectura sería poner en cola una tarea para asignar nuevos números aleatorios a las entidades que buscó, por lo que si golpea una de ellas nuevamente, no obtendrá los mismos vecinos con ella. – geoffspear

+0

@NickJohnson podría aclarar sobre el rango estándar? Perdón, ¿no entendí a qué se refería con (0..1)? Además, para los dos: me preocupa utilizar mi único filtro de desigualdad para esta operación (porque en algunas consultas necesito que sea aleatorio pero al mismo tiempo ejecute un filtro de igualdad en otra propiedad). ¿Qué tan malo es hacer 10 consultas, es básicamente 10 veces el costo? – iceanfire

3

La respuesta de Jason Hall y the one here no son horribles, pero como él menciona, tampoco son realmente aleatorias. Incluso hacer diez consultas no será aleatorio si, por ejemplo, los números aleatorios se agrupan todos juntos. Para mantener las cosas verdaderamente al azar, aquí hay dos soluciones posibles:

solución al 1

Asignar un índice para cada objeto de almacén de datos, realizar un seguimiento del índice máximo y al azar seleccionar un índice cada vez que se desea conseguir un registro aleatorio:

MyObject.objects.filter('index =', random.randrange(0, maxindex+1))

Al revés: verdaderamente aleatoria. Rápido.

Down-side: Debe mantener los índices al agregar y eliminar objetos, lo que puede hacer que ambas operaciones sean una operación O (N).

Solución 2

asignar un número aleatorio a cada número de almacén de datos cuando se crea. Luego, para obtener un registro aleatorio la primera vez, busque un registro con un número aleatorio mayor que algún otro número aleatorio y ordene por los números aleatorios (es decir, MyObject.order('rand_num').filter('rand_num >=', random.random())). A continuación, guarde esa consulta como un cursor en el Memcache. Para obtener un registro aleatorio después de la primera vez, cargue el cursor desde el Memcache y vaya al siguiente elemento. Si no hay ningún elemento después del primero, vuelva a ejecutar la consulta.

Para evitar que la secuencia de objetos se repita, en cada lectura del almacén de datos, proporcione a la entidad que acaba de leer un nuevo número aleatorio y guárdelo en el almacén de datos.

arriba del lado: verdaderamente aleatoria. No hay índices complejos para mantener.

Abajo: Necesito hacer un seguimiento de un cursor. Necesita hacer un put cada vez que obtenga un registro aleatorio.

+0

"Incluso hacer diez consultas no será aleatorio si, por ejemplo, los números aleatorios se agrupan todos juntos" - Supongo que está hablando de los números aleatorios que se asignaron a las filas del almacén de datos. Este es solo un problema para un pequeño número de registros: la desviación estándar de las brechas entre los valores se reduce a medida que aumenta el número de valores, hasta el punto en que es estadísticamente insignificante. Su solución 1 requiere un contador monotónico, que es una operación lenta y costosa en App Engine. La Solución 2 usa la selección sin reemplazo, que es diferente a lo que el OP estaba pidiendo. –

+0

Correcto, el enfoque ingenuo se rompe si no hay muchos registros o si los está recuperando a gran velocidad. Además, una vez que se establecen los valores de rand_num, su distribución es fija. No obtendrá una buena distribución uniforme y habrá ciertos registros que raramente serán seleccionados. – speedplane

+0

No, ese era mi punto: cuanto mayor sea la cantidad de registros que tenga, menor será la desviación estándar en el intervalo. Es decir, habrá proporcionalmente menos entidades que tengan intervalos anormalmente pequeños asignados a ellas. La sugerencia de Wooble de reasignar números una vez que seleccione un registro también ayudaría a contrarrestar esto. –

Cuestiones relacionadas