Как реализовать теги записей в Mongo?
Я играю с Mongo, чтобы сделать проект, подобный домашнему животному, и хочу реализовать теги post. У каждого тега есть имя и слаг (строка, которая будет использоваться в качестве идентификатора в URL), а у записи есть несколько тегов. Я хотел бы иметь возможность создавать запросы типа "найти сообщения, которые имеют тег A, не имеют тег B", и мне интересно, как это можно сделать.
Одним из способов является сохранение массива идентификаторов тегов для каждого сообщения - это облегчит указанный запрос, но потребует дополнительного для каждого сообщения, чтобы получить имя тега и фрагмент. Другой способ - сохранить массив [tag name, tag slug] с каждым сообщением, но я не уверен, что смогу использовать эту информацию в find
,
Есть какой-то другой метод, который будет работать лучше для монго? Я новичок в NoSQL, поэтому я буду признателен за любые советы о том, как это можно сделать. Кроме того, я использую привязку PHP, но это не должно иметь значения, вероятно.
1 ответ
Если теги, которые вы используете, и их соответствующие слагы вряд ли изменятся, я думаю, что ваш второй подход лучше. Однако я бы предложил небольшое изменение - вместо того, чтобы хранить массив [name, slug]
, сделайте поля явными, создав поддокумент тега, как в этом примере post
документ:
{
"_id" : ObjectId("4ee33229d8854784468cda7e"),
"title" : "My Post",
"content" : "This is a post with some tags",
"tags" : [
{
"name" : "meta",
"slug" : "34589734"
},
{
"name" : "post",
"slug" : "34asd97x"
},
]
}
Затем вы можете запросить сообщения с определенным тегом с помощью точечной нотации, например:
db.test.find({ "tags.name" : "meta"})
Так как tags
является массивом, монго достаточно умен, чтобы сопоставить запрос с любым элементом массива, а не с массивом в целом, а точечная нотация позволяет сопоставить конкретное поле.
Для запроса сообщений, не содержащих определенный тег, используйте $ne
:
db.test.find({ "tags.name" : { $ne : "fish" }})
И для запроса сообщений, содержащих один тег, но не другой, используйте $and
:
db.test.find({ $and : [{ "tags.name" : { $ne : "fish"}}, {"tags.name" : "meta"}]})
Надеюсь это поможет!