Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
870 views
in Technique[技术] by (71.8m points)

mongodb - How to implement post tags in Mongo?

I'm toying with Mongo to make a SO-like pet project, and I want to implement post tags. Each tag has a name and a slug (string to be used as an id in the URL), and a post has multiple tags. I'd like to be able to create queries like "find posts, which have tag A, don't have tag B", and I'm wondering what's the mongo-way to do this.

One way is to store an array of tag ids with each post - this will make the said query easy, but will require an extra one for each post to get tag name and a slug. Another way is to store an array of [tag name, tag slug] with each post, but I'm not sure I'll be able to use that info in a find.

Is there some other method, which will work better for mongo? I'm new to NoSQL, so I'd appreciate any advise on how this can be accomplished. Also, I'm using PHP binding, but that shouldn't matter probably.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If the tags you use and their respective slugs are unlikely to change, I think your second approach is the better one. However I would suggest a small change - rather than storing an array of [name, slug], make the fields explicit by creating a tag subdocument as in this example 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"
        },
    ]
}

You can then query for posts with a particular tag using dot notation like this:

db.test.find({ "tags.name" : "meta"})

Because tags is an array, mongo is clever enough to match the query against any element of the array rather than the array as a whole, and dot-notation allows you to match against a particular field.

To query for posts not containing a specific tag, use $ne:

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

And to query for posts containing one tag but not the other, use $and:

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

Hope this helps!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...