Filtrado de MongoDB por muchos parámetros (índice compuesto o no)
-
29-10-2019 - |
Pregunta
Tengo un catálogo con productos y quiero filtrarlo por muchos parámetros: categoría, precio, tamaño, color, peso, etc.
Entonces, la pregunta es sobre indexación.
Puedo intentar usar un índice compuesto en todos los campos y consultarlos en el mismo orden en que los indexé. Pero, ¿qué pasa si necesito filtrar solo por tamaño y color, y luego solo por precio y peso? Crear un índice compuesto para cada posible consulta de filtrado sería una exageración porque podría haber demasiados parámetros.
Entonces, después de buscar, encontré un enfoque interesante
Se sugiere utilizar "atributos normalizados":
{color: "red"} = 10
{weight: 125} = 25
{size: "M"} = 30
y ahora el registro de mongo se verá así:
{_id: ..., attributes: [10,25,30]}
Entonces debería indexar por atributos y luego puedo consultar de esta manera:
db.items.find(attributes: {$all: [10,25,30]})
Las ventajas son:
- índices más pequeños
- búsquedas más rápidas
- cualquier número de parámetros
- crecimiento fácil
Lo que no entendí es ¿CÓMO obtengo esos números para cada atributo? ¿Están calculados de alguna manera (como md5)? ¿O debería crear una colección diferente y almacenar cada clave-valor-número allí? ¿Y obtener primero los números de allí, cada vez que necesite filtrar la colección de "elementos"?
¿Y qué opinas de este enfoque?
ACTUALIZACIÓN: ¿Qué pasa si uso cadenas concatenadas en lugar de números?
{_id: ..., attributes: ["language.English", "color.red"]}
Solución
Buscar (de manera eficiente) en el catálogo de una tienda no es una tarea trivial.
Sí, puede crear una colección adicional y almacenar todos los valores allí
{name: "language", value: "English", numValue: "13"}
No, no es necesario volver a consultar esta colección cada vez.El tamaño de los datos aquí probablemente sea pequeño, por lo que puede almacenarlos en caché en el proceso de aplicación.No olvide la pista: siempre coloque primero el atributo con la cardinalidad más baja.
Otro enfoque sería utilizar enmascaramiento de bits, pero dado que MongoDB tiene una longitud entera limitada, no puede obtener un número ilimitado de atributos.