2

我们最近从关系型 (MySQL) 转向 NoSQL (couchbase)。基本上它是社交手机游戏的后端。我们在扩展后端以处理越来越多的用户时面临很多问题。当使用 MySQL 加载用户时,由于多个表之间存在大量连接,因此需要花费大量时间。特别是在加载数据时,我们看到了一个巨大的改进,因为大部分数据都保存在一个文档中。

不利的一面是,就查询而言,couchbase 似乎也有很多限制。SQL 查询的 Couchbase 替代方案是视图。虽然我们设法使用 map-reduce 处理了大部分查询,但我们确实很难弄清楚如何处理基于时间的查询。例如,我们需要根据时间戳属性过滤用户。如果时间小于当前时间,我们只需要查看用户:

if(user.time < new Date().getTime() / 1000)

发生的情况是,一旦用户的时间设置为未来某个时间,它就会从这个视图中豁免,这是所需的行为,但除非我们更新它,否则它永远不会被添加回视图 - 文档只有在它的视图中被重新索引更新。

我们现在的解决方案是先加载 x 个用户文档,然后在我们的应用程序中检查时间。排序是在 user.time 属性上完成的,所以我们得到那些时间小于或接近当前时间的用户。但我不确定这是否真的可以在现场环境中工作。理想情况下,我们希望避免在应用程序级别进行此类检查。

此外,有时我们需要检查多个基于时间的属性,例如匹配。我们当前的策略在这种情况下不起作用,我们经常从视图中获取在应用程序中完成时未通过这些检查的文档。如果已经解决过类似问题的人可以分享他们的经验,我将不胜感激。提前致谢。

更新:

我们尝试使用仅适用于一个键的范围查询。就像我说的,在大多数情况下,我们有多个基于时间的键,这意味着多个范围不起作用。

4

1 回答 1

6

如果您在视图函数中使用 Date().getTime() ,您将始终获得该视图被索引的时间,正如您所说的“除非我们更新它,否则它永远不会被添加回视图”。

有两种方法:

  1. 不好的方式(不要在生产中这样做)。使用参数查询视图stale=false。这将导致视图在返回结果之前更新。但是视图索引是一个缓慢的过程,特别是如果您有超过 100 万条记录。

  2. 好办法。使用范围请求。您只需要在 map 函数中发出您的日期作为键或复杂键的一部分并使用该范围请求。您可以在此处此处查看一个示例(如果您想在 couchbase 中使用 DateTime,此示例将更有用)。或者看看我下面的例子:

即,您将拥有以下文档:

doc = {
 "id"=1,
 "type"="doctype",
 "timestamp"=123456, //document update or creation time
 "data"="lalala"
}

对于那些文档,地图功能将如下所示:

map = function(){
 if (doc.type === "doctype"){
  emit(doc.timestamp,null);
 }
}

现在要获取最近“更新”的文档,您需要使用参数查询此视图:

startKey="dateTimeNowFromApp" 
endKey="{}"
descending=true

注意 startKey 和 endKey 是交换的,因为我使用了降序。这里还有一个关于couchbase支持的键类型的文档链接。

此外,我还找到了一个问题的链接,也可以提供帮助。

于 2013-09-16T21:29:41.727 回答