Подтвердить что ты не робот

Как реализовать теги post в Mongo?

Я играю с Mongo, чтобы сделать проект SO-like pet, и я хочу реализовать теги post. Каждый тег имеет имя и slug (строка, которая будет использоваться как идентификатор в URL-адресе), а сообщение имеет несколько тегов. Я хотел бы иметь возможность создавать запросы, такие как "найти сообщения, которые имеют тег A, не имеют тега B", и мне интересно, как это сделать mongo-way.

Один из способов заключается в том, чтобы хранить массив идентификаторов тегов с каждым сообщением - это упростит указанный запрос, но потребует дополнительного для каждого сообщения, чтобы получить имя тега и пул. Другой способ - сохранить массив каждого имени тега, тега slug, но я не уверен, что смогу использовать эту информацию в find.

Есть ли другой метод, который лучше подходит для монго? Я новичок в NoSQL, поэтому я буду признателен за любые рекомендации о том, как это можно сделать. Кроме того, я использую привязку PHP, но это не должно иметь значения.

4b9b3361

Ответ 1

Если теги, которые вы используете, и их соответствующие слизни вряд ли изменится, я думаю, что ваш второй подход лучше. Однако я бы предложил небольшое изменение - вместо хранения массива [name, slug], сделать поля явными, создав под-документ тега, как в этом примере post document:

{
    "_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 - это массив, mongo достаточно умен, чтобы сопоставлять запрос с любым элементом массива, а не с массивом в целом, а точка-нотация позволяет вам сопоставлять конкретное поле.

Чтобы запросить сообщения, не содержащие определенного тега, используйте $ne:

db.test.find({ "tags.name" : { $ne : "fish" }})

И для запроса сообщений, содержащих один тег, но не другого, используйте $and:

db.test.find({ $and : [{ "tags.name" : { $ne : "fish"}}, {"tags.name" : "meta"}]})

Надеюсь, это поможет!