支持关键字搜索的数据库模式或框架

时间:2014-12-28 14:39:24

标签: mysql regex mongodb tags database

要将关键字/标签添加到我们数据库中的某个业务对象,请调用表users。我考虑过添加tags表和usertags表,但我看不到一种简单的方法来执行包含and和{{1}的查询}。例如,我希望能够返回or A AND B的所有users,以及使用tag A或users查询tag B. OR查询很简单,但AND查询

我已经考虑过将所有user记录放入一个json支持的数据库中,这样我就可以让所有用户都像这样重复:

{
     user_id:1,
     keyword:"A",
     keyword:"B"
}

等。 但我不确定像MongoDB这样的数据库在运行这样的查询时表现如何。

另一种选择是在tags表上有一个user字段,并使用REGEX查询。在某些方面,我最喜欢这个,因为它意味着更容易进行即席查询,但我担心性能。

请注意,tag不是我们需要搜索的唯一字段,因此理想情况下,我们有一个支持日期范围搜索的解决方案以及针对其他字段的搜索。< / p>

1 个答案:

答案 0 :(得分:1)

我真的只能谈论MongoDB,所以我会坚持下去。

让我们假设一个更准确的模型,如

{
  _id: "foo@bar.com",
  keywords: [ "A", "B" ],
  joined: ISODate("2014-12-28T12:00:00.123Z"),
  tags: [ "C", "D" ],
  location: { type: "Point", coordinates: [ 38.1200538,  -86.9141607 ] },
  notes: "Lorem ipsum dolor sic amet."
 }

MongoDB中的性能或多或少取决于两个因素:您查询的字段是索引还是索引在RAM中。通常,MongoDB尝试至少保留RAM中的所有索引,并尽可能地保留大部分数据。索引字段非常简单。为了满足您的第一个要求,我们将keywords字段编入索引:

db.yourCollection.ensureIndex({ keywords: 1})

现在发生的事情是MongoDB将创建一个关键字列表和一个指向相应文档的链接。因此,如果您对关键字&#34; A&#34;

进行查询
db.yourCollection.find({keywords: "A"})

只有实际包含关键字&#34; A&#34;将被阅读并返回。这称为索引扫描。如果&#34;关键字&#34;上没有索引,MongoDB会读取集合中的每个文档,检查包含的关键字字段&#34; A&#34;并将相应的文档添加到结果集中,称为集合扫描。

现在,检查包含&#34; A&#34;的文档。和&#34; B&#34;关键字,这很简单:

db.yourCollection.find({$or: [ {keywords:"A"}, {keywords:"B"} ] })

由于我们已将&#34;关键字编入索引&#34;字段,逻辑检查在RAM中完成,相应的文档将添加到结果集中。

对于正则表达式搜索,对于索引字段,它们绝对可行且非常快:

db.yourCollection.find({keywords: /^C.*/i})

将返回包含以字母&#34; c&#34;开头的关键字的所有文档。 (不区分大小写)使用索引扫描。

至于您对日期范围进行查询的要求:

db.yourCollection.find({joined:
 {
  $gte: ISODate("2014-12-28T00:00:00.000Z"),
  $lt: ISODate("2014-12-29T00:00:00.000Z")
 }
})

将返回2014年12月28日加入的所有用户。由于我们尚未在该字段上创建索引,因此将使用收集扫描。当然,你可以在&#34;加入&#34;字段。

因此,我们假设您想要找到所有拥有关键字的用户&#34; A&#34;来自圣诞老人,IN:

db.yourCollection.find({
  keywords: "A", 
  location: {
    $nearSphere : {
      $geometry: {
        type : "Point",
        coordinates: [ 38.1200538,  -86.9141607 ]
      },
      $minDistance: 0,
      $maxDistance: 10000
    }
  }
})

这将返回......没有,iirc,因为我们必须首先创建geospatial index

db.collection.ensureIndex( { location : "2dsphere" } )

现在提到的查询将按预期工作。

结论

MongoDB可以满足您的要求,并且具有良好性能的正确索引。但是,您可能希望深入了解MongoDBs的限制。

您可能想要阅读更多内容。以下是我的建议:

  1. Introduction to MongoDB
  2. Index documentation
  3. Data modelling introduction