2011-04-08 13 views
10

Tengo un requisito particular de manipulación de datos que he resuelto cómo hacerlo en SQL Server y PostgreSQL. Sin embargo, no estoy muy contento con la velocidad, así que estoy investigando MongoDB.Idoneidad de MongoDB para consultas de tipo jerárquico

La mejor manera de describir la consulta es la siguiente. Imagine los datos jerárquicos de los EE. UU .: País, Estado, Condado, Ciudad. Digamos que un vendedor en particular puede dar servicio a toda California. Otra puede servir solo a Los Angeles. Existen potencialmente cientos de miles de proveedores y todos pueden ofrecer servicio desde algún punto (s) en esta jerarquía. No estoy confundiendo esto con Geo: estoy usando esto para ilustrar la necesidad.

Usando consultas recursivas, es bastante simple obtener una lista de todos los proveedores que podrían dar servicio a un usuario en particular. Si estuviera en, digamos, Pasadena, Los Ángeles, California, subiríamos por la jerarquía para obtener los ID correspondientes, luego volveríamos a consultar para encontrar los proveedores.

Sé que esto se puede optimizar. De nuevo, esto es solo un simple ejemplo de consulta.

Sé que MongoDB es una tienda de documentos. Eso satisface otras necesidades que tengo muy bien. La pregunta es: ¿qué tan apropiado es para el tipo de consulta que describo? (Sé que no tiene combinaciones, esas son simuladas).

Entiendo que esta es una pregunta "¿cuánto tiempo es una cuerda?". Solo quiero saber si alguien tiene alguna experiencia con MongoDB haciendo este tipo de cosas. Podría tomar bastante tiempo pasar de 0 a probado, y estoy buscando ahorrar tiempo si MongoDB no es adecuado para esto.

Ejemplo

Una tienda local de la película "A" puede suministrar Blu-Rays en Springfield. Una cadena de tiendas "B" con distribución en todo el estado puede suministrar Blu-Rays a todos los IL. Y una tienda de descarga por demanda "C" puede suministrar a todos los EE. UU.

Si quisiéramos obtener todos los proveedores de películas aplicables para Springfield, IL, la respuesta sería [A, B, C].

En otras palabras, hay numerosos proveedores conectados a diferentes niveles en la jerarquía.

+0

Tradicionalmente, una clave compuesta fácilmente podrían hacer esto. Sin embargo, ese no es el estilo de consulta que estoy buscando. – IamIC

Respuesta

7

Me di cuenta que pregunta fue hecha hace casi un año, pero desde entonces MongoDB tiene una solución con apoyo oficial para este problema, y ​​acabo de utilizar su solución. Consulte su documentación aquí: http://www.mongodb.org/display/DOCS/Trees+in+MongoDB

La parte relacionada más cercana a su pregunta se encuentra en la sección "ruta parcial" de la página.

Si bien puede incomodar un poco los datos del antecesor; este enfoque es la forma más adecuada para resolver su problema en MongoDB. El único inconveniente de esto, que he experimentado hasta ahora, es que si está almacenando todo esto en un solo documento, puede alcanzar el límite de tamaño de documento de 16 MB cuando trabaje con suficiente información (aunque, Solo puedo ver que esto ocurra si está utilizando esta estructura para rastrear las referencias de los usuarios [que podrían llegar a millones] en lugar de las ciudades de los EE. UU. [Que son más de 26,000 según el último Censo de EE. UU.]).


Referencias:

http://www.mongodb.org/display/DOCS/Schema+Design

http://www.census.gov/geo/www/gazetteer/places2k.html

+0

Gracias @Caleb! Esto realmente me ayuda. Es curioso, acabo de regresar a este proyecto hace 2 días y tu respondiste entonces. – IamIC

+0

También se me ocurrió que geo es una buena manera de resolver esto. – IamIC

+0

Aha, originalmente habías escrito que querías evitar Geo ... Pensé que lo estabas usando para categorías y productos, como es el caso más común para este tipo de estructura. :) –

2

Tenga en cuenta que esta pregunta también se formuló en el grupo de google. Ver http://groups.google.com/group/mongodb-user/browse_thread/thread/5cd5edd549813148 para esa disucsion.

Una opción es usar una tecla de matriz. Puede almacenar la jerarquía como una matriz de valores (por ejemplo ['US', 'CA', 'Los Angeles']).A continuación, puede consulta con los registros de la base de elementos individuales de ese conjunto de teclas Por ejemplo: En primer lugar, almacenar algunos documentos con el valor de la matriz que representa la jerarquía

> db.hierarchical.save({ location: ['US','CA','LA'], name: 'foo'}) 
> db.hierarchical.save({ location: ['US','CA','SF'], name: 'bar'}) 
> db.hierarchical.save({ location: ['US','MA','BOS'], name: 'baz'}) 

Asegúrese de que tengamos un índice en el campo de ubicación por lo que podemos realizar consultas rápidas contra sus valores

> db.hierarchical.ensureIndex({'location':1}) 

buscar todos los registros en California

> db.hierarchical.find({location: 'CA'}) 
{ "_id" : ObjectId("4d9f69cbf88aea89d1492c55"), "location" : [ "US", "CA", "LA" ], "name" : "foo" } 
{ "_id" : ObjectId("4d9f69dcf88aea89d1492c56"), "location" : [ "US", "CA", "SF" ], "name" : "bar" } 

buscar todos los registros en Massachusetts

> db.hierarchical.find({location: 'MA'}) 
{ "_id" : ObjectId("4d9f6a21f88aea89d1492c5a"), "location" : [ "US", "MA", "BOS" ], "name" : "baz" } 

buscar todos los registros en los EE.UU.

> db.hierarchical.find({location: 'US'}) 
{ "_id" : ObjectId("4d9f69cbf88aea89d1492c55"), "location" : [ "US", "CA", "LA" ], "name" : "foo" } 
{ "_id" : ObjectId("4d9f69dcf88aea89d1492c56"), "location" : [ "US", "CA", "SF" ], "name" : "bar" } 
{ "_id" : ObjectId("4d9f6a21f88aea89d1492c5a"), "location" : [ "US", "MA", "BOS" ], "name" : "baz" } 

Tenga en cuenta que en este modelo, los valores de la matriz tendría que ser único. Entonces, por ejemplo, si tuvieras 'springfield' en diferentes estados, , entonces necesitarías hacer un trabajo extra para diferenciar.

> db.hierarchical.save({location:['US','MA','Springfield'], name: 'one' }) 
> db.hierarchical.save({location:['US','IL','Springfield'], name: 'two' }) 
> db.hierarchical.find({location: 'Springfield'}) 
{ "_id" : ObjectId("4d9f6b7cf88aea89d1492c5b"), "location" : [ "US", "MA", "Springfield"], "name" : "one" } 
{ "_id" : ObjectId("4d9f6b86f88aea89d1492c5c"), "location" : [ "US", "IL", "Springfield"], "name" : "two" } 

Usted puede superar esto mediante el uso del operador $ todo y especificando más niveles de la jerarquía. Por ejemplo:

> db.hierarchical.find({location: { $all : ['US','MA','Springfield']} }) 
{ "_id" : ObjectId("4d9f6b7cf88aea89d1492c5b"), "location" : [ "US", "MA", "Springfield"], "name" : "one" } 
> db.hierarchical.find({location: { $all : ['US','IL','Springfield']} }) 
{ "_id" : ObjectId("4d9f6b86f88aea89d1492c5c"), "location" : [ "US", "IL", "Springfield"], "name" : "two" } 
+0

gracias; Entiendo lo que has demostrado. Sin embargo, ¿cómo obtendría los resultados para "darme todos los proveedores que se asignan a Springfield | MA | US"? (| ser binario O, nos dio una unión establecida). – IamIC

+0

¿No es solo db.hierarchicla.find ({location: 'US'})? MA y Springfield son subconjuntos, por lo que no se requiere OR o unión. – jared

+0

No. Mire el ejemplo que agregué a la pregunta. – IamIC

Cuestiones relacionadas