您将如何在MongoDB中有效地实现这些查询?

时间:2022-12-09 12:40:38

Links have one or more tags, so at first it might seem natural to embed the tags:

链接有一个或多个标记,因此首先嵌入标记似乎很自然:

link = { title: 'How would you implement these queries efficiently in MongoDB?'
         url: 'http://*.com/questions/3720972'
         tags: ['ruby', 'mongodb', 'database-schema', 'database-design', 'nosql']}

How would these queries be implemented efficiently?

如何有效地实现这些查询?

  • Get links that contain one or more given tags (for searching links with given tags)
  • 获取包含一个或多个给定标记的链接(用于搜索具有给定标记的链接)

  • Get a list of all tags without repetition (for search box auto-completion)
  • 获取所有标签的列表,不重复(搜索框自动完成)

  • Get the most popular tags (to display top 10 tags or a tag cloud)
  • 获取最受欢迎的标签(显示前10个标签或标签云)

The idea to represent the link as above is based on the MongoNY presentation, slide 38.

如上所述表示链接的想法基于MongoNY演示,幻灯片38。

2 个解决方案

#1


4  

Get links that contain "value" tag:

获取包含“value”标记的链接:

db.col.find({tags: "value"});

Get links that contain "val1", "val2" tags:

获取包含“val1”,“val2”标签的链接:

db.col.find({tags: { $all : [ "val1", "val2" ] }});

Get list of all tags without repetition:

获取所有标签的列表,不重复:

db.col.distinct("tags");

Get the most popular tags - this isn't something that can be queried on an existing db, what you need to do is add a popularity field update it whenever a query fetches the document, and then do a query with the sort field set to the popularity.

获取最流行的标签 - 这不是可以在现有数据库上查询的内容,您需要做的是在查询获取文档时添加流行度字段更新它,然后执行查询,并将排序字段设置为人气。

Update: proposed solution for popularity feature. Try adding the following collection, let's call it tags.

更新:建议的流行功能解决方案。尝试添加以下集合,我们称之为标记。

doc = { tag: String, pop: Integer }

doc = {tag:String,pop:Integer}

now once you do a query you collect all the tags that were shown (these can be aggregated and done asynchronously) so let's say you end up with the following tags: "tag1", "tag2", "tag3".

现在,一旦你进行查询,你就会收集所有显示的标签(这些标签可以聚合并异步完成),所以假设你最终得到以下标签:“tag1”,“tag2”,“tag3”。

You then call the update method and increment the pop field value:

然后调用update方法并增加pop字段值:

db.tags.update({tag: { $in: ["tag1", "tag2", "tag3"] }}, { $inc: { pop: 1 }});

#2


0  

You can also use $addToSet to change your tag array instead of $push. This doesn't modify the document when tag already exists. This will be a bit more efficient if you modify your tags frequently (as the documents won't grow that much). Here is an example:

您还可以使用$ addToSet来更改标记数组而不是$ push。当标记已存在时,这不会修改文档。如果您经常修改标签(因为文档不会增长那么多),这将更有效。这是一个例子:

> db.tst_tags.remove()
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag3'}}, true)
> db.tst_tags.find()
{ "_id" : ObjectId("4ce244548736000000003c6f"), "name" : "test", 
  "tags" : [ "tag1", "tag2", "tag3" ] }

#1


4  

Get links that contain "value" tag:

获取包含“value”标记的链接:

db.col.find({tags: "value"});

Get links that contain "val1", "val2" tags:

获取包含“val1”,“val2”标签的链接:

db.col.find({tags: { $all : [ "val1", "val2" ] }});

Get list of all tags without repetition:

获取所有标签的列表,不重复:

db.col.distinct("tags");

Get the most popular tags - this isn't something that can be queried on an existing db, what you need to do is add a popularity field update it whenever a query fetches the document, and then do a query with the sort field set to the popularity.

获取最流行的标签 - 这不是可以在现有数据库上查询的内容,您需要做的是在查询获取文档时添加流行度字段更新它,然后执行查询,并将排序字段设置为人气。

Update: proposed solution for popularity feature. Try adding the following collection, let's call it tags.

更新:建议的流行功能解决方案。尝试添加以下集合,我们称之为标记。

doc = { tag: String, pop: Integer }

doc = {tag:String,pop:Integer}

now once you do a query you collect all the tags that were shown (these can be aggregated and done asynchronously) so let's say you end up with the following tags: "tag1", "tag2", "tag3".

现在,一旦你进行查询,你就会收集所有显示的标签(这些标签可以聚合并异步完成),所以假设你最终得到以下标签:“tag1”,“tag2”,“tag3”。

You then call the update method and increment the pop field value:

然后调用update方法并增加pop字段值:

db.tags.update({tag: { $in: ["tag1", "tag2", "tag3"] }}, { $inc: { pop: 1 }});

#2


0  

You can also use $addToSet to change your tag array instead of $push. This doesn't modify the document when tag already exists. This will be a bit more efficient if you modify your tags frequently (as the documents won't grow that much). Here is an example:

您还可以使用$ addToSet来更改标记数组而不是$ push。当标记已存在时,这不会修改文档。如果您经常修改标签(因为文档不会增长那么多),这将更有效。这是一个例子:

> db.tst_tags.remove()
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag1'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag2'}}, true)
> db.tst_tags.update({'name':'test'},{'$addToSet':{'tags':'tag3'}}, true)
> db.tst_tags.find()
{ "_id" : ObjectId("4ce244548736000000003c6f"), "name" : "test", 
  "tags" : [ "tag1", "tag2", "tag3" ] }