Fecha publicación: Jul 12, 2021

MongoDb índices: wildcard

Hay casos, en los que no sabemos sobre que campos se van a realizar las búsquedas, y tenemos que dar un buen rendimiento desde el día cero, una opción que tenemos es ir creando índices campo por campo, ...mantener esto puede convertirse en algo pesado.

MongoDb a partir de la versión 4.2 nos ofrece los índices WildCard, que usando un carácter comodín (el asterisco) nos permite indicarle partir de que nivel en el documento cree índices para todos los campos.

Manos a la obra

Veamos como funciona esto con un ejemplo:

Trabajaremos sobre el juego de datos de ejemplo AirBnb (en el vídeo anterior te indicamos donde puedes encontrarlo), lo primero que vamos a hacer es borrar todo los índices para asegurarnos de que partimos limpios.

use airbnb
db.listingsAndReviews.dropIndexes();

Vamos trabajar con la colección listingAndReview en concreto con el campo reviews_score, vemos que es un objeto que contiene 7 campos.

reviews score campos

Este objeto tiene pinta de ser buen candidato para aplicar índices wildcard:

  • Es una puntuación por varios tópicos (puntualidad, limpieza, comunicación, sitio...).
  • Es muy normal que no haya un patrón definido de búsqueda para estos campos.
  • Es buena idea tenerlos todos indexados por si acaso.

Vamos a tirar un par de consultas y ver cómo se portan sin índices

db.listingsAndReviews.find({
  "review_scores.location": { $gte: 9 },
});
db.listingsAndReviews.find({
  "reviews_scores.cleanliness": { $gte: 9 },
});

Tenemos el problema de siempre, tiramos de colscan y recorremos todos los documentos.

En vez de crear un índice por cada campo vamos a crear un wildcard index:

  • Le indicamos que quermos aplicarlo a partir del nivel de reviews_score
  • Con el comodín $** le indicamos que cubra todos los campos de ese objeto.
db.listingsAndReviews.createIndex({ "reviews_score.$**": 1 });

Esto crea un índice por cada campo del objeto reviews_score, si ahora volvemos a lanzar las consultas

db.listingsAndReviews.find({
  "review_scores.location": { $gte: 9 },
});
db.listingsAndReviews.find({
  "reviews_scores.cleanliness": { $gte: 9 },
});

Podemos ver que se están aplicando los índices y sólo recorremos los documentos que tienen una puntuación mayor que 9.

¿Y qué pasa si el campo es de tipo array? podemos crear también un índice de este tipo, veamos por ejemplo el campo reviews

reviews, arrays de objetos  con opiniones

Vamos a tirar un par de consultas y ver cómo se portan sin índices

db.listingsAndReviews.find({
  "reviews.date": { $gte: new Date("2019-03-03") },
});
db.listingsAndReviews.find({
  "reviews.reviewer_name": "Matt",
});

Creamos un índice wildcard que cubra todas las entradas de reviews:

db.listingsAndReviews.createIndex({ "reviews.$**": 1 });

Ahora, si volvemos lanzar estás consultas podemos ver que los índices están creados para todos los campos del objeto reviews.

db.listingsAndReviews.find({
  "reviews.date": { $gte: new Date("2019-03-03") },
});
db.listingsAndReviews.find({
  "reviews.reviewer_name": "Matt",
});

Los índices wildcard pueden ser de grand utilidad cuando no sabes a ciencia cierta sobre que va a filtrar el usuario, es un caso especial, no es un sustituto de los índices tradicionales, siempre tienes que estudiar el uso de tus datos, en algunas ocasiones puede ser mucho más útil un índice por múltiples campos que un wildcard.

¿Con ganas de aprender Backend?

En Lemoncode impartimos un Bootcamp Backend Online, centrado en stack node y stack .net, en él encontrarás todos los recursos necesarios: clases de los mejores profesionales del sector, tutorías en cuanto las necesites y ejercicios para desarrollar lo aprendido en los distintos módulos. Si quieres saber más puedes pinchar aquí para más información sobre este Bootcamp Backend.