Пригодность MongoDB для запросов иерархического типа
У меня есть конкретное требование к обработке данных, которое я разработал, как это сделать в SQL Server и PostgreSQL. Тем не менее, я не слишком доволен скоростью, поэтому я изучаю MongoDB.
Лучший способ описать запрос состоит в следующем. Изобразите иерархические данные США: Страна, Штат, Графство, Город. Скажем, конкретный поставщик может обслуживать всю Калифорнию. Другой, возможно, может обслуживать только Лос-Анджелес. Есть потенциально сотни тысяч продавцов, и все они могут обслуживать от некоторых точек (ов) в этой иерархии. Я не смешиваю это с Geo - я использую это, чтобы проиллюстрировать необходимость.
Используя рекурсивные запросы, довольно просто получить список всех поставщиков, которые могут обслуживать определенного пользователя. Если бы он был в Пасадене, Лос-Анджелес, Калифорния, мы бы поднялись по иерархии, чтобы получить соответствующие идентификаторы, а затем запросить назад, чтобы найти поставщиков.
Я знаю, что это можно оптимизировать. Опять же, это простой пример запроса.
Я знаю, что MongoDB - это хранилище документов. Что подходит для других потребностей, я очень хорошо себя чувствую. Вопрос в том, насколько хорошо он подходит к типу запроса, который я описываю? (Я знаю, что у него нет объединений - моделируются).
Я понимаю, что это вопрос длительности строки. Я просто хочу знать, есть ли у кого-нибудь опыт работы с MongoDB. Мне может потребоваться некоторое время, чтобы перейти от 0 до тестируемого, и я хочу сэкономить время, если MongoDB не подходит для этого.
Пример
Местный кинотеатр "А" может поставлять Blu-Ray в Спрингфилде. Сетевой магазин "B" с распределением по всему миру может поставлять Blu-Ray для всего IL. И магазин "C" для загрузки по требованию может поставляться всем США.
Если бы мы хотели получить всех применимых поставщиков фильмов для Springfield, IL, ответ был бы [A, B, C].
Другими словами, существует множество поставщиков, прикрепленных на разных уровнях иерархии.
Ответы
Ответ 1
Я понимаю, что этот вопрос задавали почти год назад, но с тех пор MongoDB официально поддерживает решение этой проблемы, и я просто использовал их решение. Обратитесь к их документации здесь: http://www.mongodb.org/display/DOCS/Trees+in+MongoDB
Часть, относящаяся ближе всего к вашему вопросу, находится в разделе "частичный путь" на странице.
Хотя может показаться немного тяжелым, чтобы вставлять данные предка; этот подход является наиболее подходящим способом решения вашей проблемы в MongoDB. Единственное, что я испытал до сих пор, заключается в том, что если вы сохраните все это в одном документе, вы можете на время ограничить размер документа размером 16 МБ при работе с достаточным количеством данных (хотя, Я могу видеть это только в том случае, если вы используете эту структуру для отслеживания рефералов пользователей [которые могут достигать миллионов], а не городов США [которые превышают 26 000 в соответствии с последней переписью США]).
Литература:
http://www.mongodb.org/display/DOCS/Schema+Design
http://www.census.gov/geo/www/gazetteer/places2k.html
Ответ 2
Обратите внимание, что этот вопрос также задавался в группе google. См. http://groups.google.com/group/mongodb-user/browse_thread/thread/5cd5edd549813148 для этого расчленения.
Один из вариантов - использовать ключ массива. Вы можете сохранить иерархию как
массив значений (например, ['US', 'CA', 'Los Angeles']). Тогда ты можешь
запрос к записям на основе отдельных элементов в этом ключе массива
Например:
Сначала сохраните некоторые документы со значением массива, представляющим
иерархия
> 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'} )
Удостоверьтесь, что у нас есть индекс в поле местоположения, чтобы мы могли выполнять
быстрые запросы против его значений
> db.hierarchical.ensureIndex({'location':1})
Найти все записи в Калифорнии
> db.hierarchical.find({location: 'CA'})
{ "_id" : ObjectId("4d9f69cbf88aea89d1492c55"), "location" : [ "US", "CA", "LA" ], "name" : "foo" }
{ "_id" : ObjectId("4d9f69dcf88aea89d1492c56"), "location" : [ "US", "CA", "SF" ], "name" : "bar" }
Найти все записи в Массачусетсе
> db.hierarchical.find({location: 'MA'})
{ "_id" : ObjectId("4d9f6a21f88aea89d1492c5a"), "location" : [ "US", "MA", "BOS" ], "name" : "baz" }
Найти все записи в США
> 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" }
Обратите внимание, что в этой модели ваши значения в массиве должны быть
уникальный. Например, если у вас было "весеннее поле" в разных государствах,
то вам нужно будет сделать дополнительную работу для дифференциации.
> 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" }
Вы можете преодолеть это, используя оператор $all и указав больше
уровни иерархии. Например:
> 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" }