要将关键字/标签添加到我们数据库中的某个业务对象,请调用表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>
答案 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的限制。
您可能想要阅读更多内容。以下是我的建议: