Disfruté creando un par de aplicaciones simples en el GAE, pero ahora estoy perplejo acerca de cómo diseñar un organizador de colección de música en el motor de la aplicación. En resumen, no puedo encontrar la manera de filtrar varias propiedades al ordenar otras.

Supongamos que el modelo principal es un álbum que contiene varias propiedades, que incluyen:

  • Título
  • Artista
  • Etiqueta
  • Año de publicación
  • Género
  • Longitud
  • Lista de nombres de pistas
  • Lista de estados de ánimo
  • Fecha y hora de inserción en la base de datos

Supongamos también que me gustaría filtrar toda la colección usando esas propiedades, y luego ordenar los resultados por uno de:

  • Año de publicación
  • Duración del álbum
  • Nombre del artista
  • Cuando la información fue agregada a la base de datos

No sé cómo hacer esto sin toparme con el enigma del índice explosivo. Específicamente, me encantaría hacer algo como:

Albums.all().filter('publication_year <', 1980).order('artist_name')

Sé que eso no es posible, pero ¿cuál es la solución?

Esto parece un tipo de aplicación bastante general. Los álbumes de música pueden ser restaurantes, botellas de vino u hoteles. Tengo una colección de elementos con propiedades descriptivas que me gustaría filtrar y ordenar.

¿Hay un diseño de modelo de datos de mejores prácticas que estoy pasando por alto? ¿Algún consejo?

1
Greg 31 jul. 2009 a las 21:55

2 respuestas

La mejor respuesta

Aquí hay un par de opciones: puede filtrar lo mejor posible, luego ordenar los resultados en la memoria, como sugiere Alex, o puede reelaborar sus estructuras de datos para filtros de igualdad en lugar de filtros de desigualdad.

Por ejemplo, suponiendo que solo desee filtrar por década, puede agregar un campo que codifique la década en la que se grabó la canción. Para encontrar todo antes o después de una década, haga una consulta IN para las décadas que desea abarcar. Esto requerirá una consulta subyacente por década incluida, pero si el número de registros es grande, aún puede ser más barato que obtener todos los resultados y ordenarlos en la memoria.

1
Nick Johnson 1 ago. 2009 a las 10:27

Dado que el almacenamiento es económico, puede crear sus propios archivos de índice basados en ListProperty con key_names que reflejen los criterios de clasificación.

class album_pubyear_List(db.Model):
    words = db.StringListProperty()

class album_length_List(db.Model):
    words = db.StringListProperty()

class album_artist_List(db.Model):
    words = db.StringListProperty()

class Album(db.Model):
    blah...

    def save(self):
        super(Album, self).save()

        # you could do this at save time or batch it and do
        # it with a cronjob or taskqueue

        words = []

        for field in ["title", "artist", "label", "genre", ...]:
            words.append("%s:%s" %(field, getattr(self, field)))

        word_records = []
        now = repr(time.time())
        word_records.append(album_pubyear_List(parent=self, key_name="%s_%s" %(self.pubyear, now)), words=words)
        word_records.append(album_length_List(parent=self, key_name="%s_%s" %(self.album_length, now)), words=words)
        word_records.append(album_artist_List(parent=self, key_name="%s_%s" %(self.artist_name, now)), words=words)
        db.put(word_records)

Ahora, cuando llega el momento de buscar, crea una cláusula WHERE apropiada y llama al modelo apropiado

where = "WHERE words = " + "%s:%s" %(field-a, value-a) + " AND " + "%s:%s" %(field-b, value-b) etc.
aModel = "album_pubyear_List" # or anyone of the other key_name sorted wordlist models

indexes = db.GqlQuery("""SELECT __key__ from %s %s""" %(aModel, where))
keys = [k.parent() for k in indexes[offset:numresults+1]] # +1 for pagination
object_list = db.get(keys) # returns a sorted by key_name list of Albums
1
molicule 3 ago. 2009 a las 03:06