forma más eficiente para que coincida con un cierto número de elementos de una db.Model ListProperty

StackOverflow https://stackoverflow.com/questions/1197330

Pregunta

En referencia a esta pregunta diferente, pero no sin relación lo haré prestado los modelos de ejemplo.

class Foo(db.Model): bars = db.ListProperty(db.Key)

class Bar(db.Model): pass

Si tengo una cierta entidad Foo y quiero conseguir todas las otras entidades foo también contienen una cierta clave de barras en sus bares ListProperty, me gustaría utilizar la siguiente consulta:

related_foos = Foo.all().filter('bars', bar_entity).fetch(fetch_count) 

¿Qué pasa si quiero encontrar todas las otras entidades del modelo de tipo Foo que tienen al menos un número N de entidades a juego de barras? La manera obvia de hacer esto con un bucle para que implicaría ineficiencias drásticas, y puede ser que sea mejor para realmente cambiar el modelo en sí mismo para hacer esto más fácil, pero no parece obvio cómo hacerlo.

¿Fue útil?

Solución

Dado un registro foo que tiene 10 bar_entities y en busca de todos los registros foo que tienen al menos 2 de estos 10 entidades se traduciría en 45 posible la igualdad de valores de 10! / (2 * (10-2)!) = 45.

Esto puede deducirse en 10_C_ (2-1) = 10 lee.

SELECT * from table WHERE bar="1" AND bar in ["2", "3", "4", "5", "6", "7", "8", "9", "0"]
SELECT * from table WHERE bar="2" AND bar in ["3", "4", "5", "6", "7", "8", "9", "0"]
SELECT * from table WHERE bar="3" AND bar in ["4", "5", "6", "7", "8", "9", "0"]
etc.

Para reducir esto a una lectura requeriría que cuando se agrega un registro foo que rellenar una tabla separada que tenía todas las combinaciones 2 para un registro dado.

Say you had

foo_table
foo1 [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
foo2 [1, 3, 4]
foo3 [1, 2, a]
foo4 [b, 6, c]

foo_combo_2_table
Parent  Combination
foo1    12
foo1    13
... and all 45 foo1 combinations each in its own row
foo2    13
foo2    14
foo2    34
foo3    12
foo3    1a
foo3    2a
etc.

Now you can do a 

indexes = SELECT __KEY__ from foo_combo_2_table WHERE combination IN [12, 13, 14, 15, ... all 45]
keys = [k.parent() for k in indexes] # you would need to filter for duplicates

De esta manera usted no conseguirá en cualquier problema de índice de estallido.

Si también quería hacer cualquiera de los 3 o cualquiera de las 4 entidades que para cada uno de éstos lo que se necesita para crear un foo_combo_n_table o hacer un número 10_C_ (n-1) de las lecturas.

Otros consejos

Simplemente puede aplicar el mismo filtro varias veces:

related_foos = Foo.all().filter('bars', bar_entity).filter('bars', bar_entity_2).fetch(fetch_count)

O, impulsado por los datos:

q = Foo.all()
for bar in bar_entities:
  q.filter('bars', bar)
related_foos = q.fetch(fetch_count)

Si usted no aplica ningún desigualdades o criterios de ordenación de la consulta, el almacén de datos será capaz de ejecutar las consultas utilizando el construido en los índices y la combinación de estrategia de combinación, independientemente del número de filtros que se aplican. Si necesita una orden desigualdad o la especie, sin embargo, usted necesita tener un índice para cada número de barras es posible que desee filtrar, lo que conduce a la explosión de índices (y por lo tanto es mejor evitarlo!)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top