2010-09-15 12 views
6

enlaces tienen una o más etiquetas, por lo que en principio puede parecer natural para incrustar los tags:¿Cómo implementaría estas consultas de manera eficiente en MongoDB?

link = { title: 'How would you implement these queries efficiently in MongoDB?' 
     url: 'http://stackoverflow.com/questions/3720972' 
     tags: ['ruby', 'mongodb', 'database-schema', 'database-design', 'nosql']} 

cómo se aplicaría estas consultas de manera eficiente?

  • Enlaces que contienen una o más etiquetas dadas (para buscar vínculos con etiquetas dados)
  • obtener una lista de todas las etiquetas sin repetición (para la búsqueda de caja de autocompletar)
  • Recibe las etiquetas más populares (para mostrar los 10 mejores etiquetas o una nube de etiquetas)

la idea de representar el enlace que arriba se basa en la MongoNY presentation, deslice 38.

Respuesta

4

Obtener enlaces que contienen la etiqueta "valor" :

db.col.find({tags: "value"}); 

Enlaces que contienen "val1", etiquetas "val2":

db.col.find({tags: { $all : [ "val1", "val2" ] }}); 

obtener la lista de todas las etiquetas sin repetición:

db.col.distinct("tags"); 

Obtener las etiquetas más populares - este no es algo que se pueda consultar en una base de datos existente, lo que debe hacer es agregar un campo de popularidad actualizar cada vez que una consulta recupera el documento, y luego hacer una consulta con el campo de clasificación establecido en la popularidad.

Actualización: solución propuesta para la función de popularidad. Intente agregar la siguiente colección, vamos a llamarlo etiquetas.

doc = {tag: Cadena, pop: Entero}

ahora, una vez que usted una consulta recoja todas las etiquetas que fueron mostrados (estos pueden ser agregados y hecho de forma asíncrona) Así que digamos que usted termina con el siguientes etiquetas: "tag1", "tag2", "tag3".

A continuación, llama al método de actualización e incrementar el valor del campo emergente:

db.tags.update({tag: { $in: ["tag1", "tag2", "tag3"] }}, { $inc: { pop: 1 }}); 
+0

Con el fin de agregar un campo de popularidad para una etiqueta, tendría que ser añadido o se mueve en una recogida selectiva, la etiqueta correcta? – randomguy

+0

no es necesario, puede guardarlo en la misma colección y simplemente usar un dbref para señalar la etiqueta. una colección diferente simplificará la administración de sus datos (que es lo que recomiendo). – Asaf

+0

En la colección de etiquetas, sugiero poner el nombre de la etiqueta en el campo _id en lugar de usar un campo de etiqueta separado. Además, si no le importa hacer una actualización por etiqueta en lugar de usar $ in, puede hacer que la consulta sea solo {_id: "tag_name"} y use la función de inserción para crear nuevas entradas de etiqueta. – mstearn

0

También puede utilizar $ addToSet para cambiar la matriz de la etiqueta en lugar de $ empujón. Esto no modifica el documento cuando la etiqueta ya existe. Esto será un poco más eficiente si modifica las etiquetas con frecuencia (ya que los documentos no crecerán tanto). Aquí se muestra un ejemplo:

> db.tst_tags.remove() 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true) 
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag3'}}, true) 
> db.tst_tags.find() 
{ "_id" : ObjectId("4ce244548736000000003c6f"), "name" : "test", 
    "tags" : [ "tag1", "tag2", "tag3" ] } 
Cuestiones relacionadas