Ответ 1
Первое, что вы хотите решить, это то, какое именно дерево вы будете использовать.
Важно учитывать ваши данные и схемы доступа. Вы уже заявили, что 90% всей вашей работы будут запрашивать, и, судя по звукам ее (электронной коммерции), обновления будут выполняться только администраторами, скорее всего, редко.
Итак, вам нужна схема, которая дает вам возможность быстро запрашивать информацию о ребенке по дорожке, а именно: Спорт → Баскетбол → Мужчины, Спорт → Теннис → Женщины, и на самом деле не нужно действительно масштабировать ее до обновлений.
Как вы правильно заметили, у MongoDB есть хорошая страница документации для этого: https://docs.mongodb.com/manual/applications/data-models-tree-structures/, где 10gen на самом деле устанавливает различные модели и методы схемы для деревьев и описывает основные взлеты и падения из них.
Тот, который должен бросаться в глаза, если вы ищете простой запрос, это материализованные пути: https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/
Это очень интересный метод построения деревьев, поскольку для запроса на приведенном выше примере в "Womens" в "Tennis" вы можете просто выполнить предопределенное регулярное выражение (которое может использовать индекс: http://docs.mongodb.org/manual/reference/operator/regex/) примерно так:
db.products.find({category: /^Sports,Tennis,Womens[,]/})
найти все продукты, перечисленные под определенным путем вашего дерева.
К сожалению, эта модель плохо подходит для обновления, если вы перемещаете категорию или меняете ее название, вам нужно обновить все продукты, и в одной категории могут быть тысячи продуктов.
Лучшим способом было бы разместить cat_id
на продукте, а затем разделить категории в отдельную коллекцию со схемой:
{
_id: ObjectId(),
name: 'Women\'s',
path: 'Sports,Tennis,Womens',
normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}
Так что теперь ваши запросы включают только коллекцию категорий, которая должна сделать их намного меньше и более производительными. Исключением является то, что когда вы удаляете категорию, продукты все равно нужно трогать.
Итак, пример изменения "Теннис" на "Бадмин":
db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
doc.path = doc.path.replace(/,Tennis/, ",Badmin");
db.categories.save(doc);
});
К сожалению, в настоящее время MongoDB не обеспечивает отображение документов в запросе, поэтому вам действительно нужно вытащить их из клиентской части, что немного раздражает, однако, надеюсь, это не должно привести к возвращению слишком большого количества категорий.
И это в основном, как это работает на самом деле. Обновление немного проблематично, но, я полагаю, возможность мгновенного запроса по любому пути с использованием индекса больше подходит для вашего сценария.
Конечно, дополнительное преимущество заключается в том, что эта схема совместима с моделями вложенных множеств: http://en.wikipedia.org/wiki/Nested_set_model, которые, как я обнаружил снова и снова, просто великолепны для сайтов электронной коммерции, например, для тенниса. может быть под "Спорт" и "Досуг", и вы хотите несколько путей в зависимости от того, откуда пользователь пришел.
Схема для материализованных путей легко поддерживает это, просто добавляя другой простой path
.
Надеюсь, что это имеет смысл, довольно долго там.