我们最近从关系(MySQL)转向NoSQL(couchbase)。基本上它是社交手机游戏的后端。我们在扩展后端以处理越来越多的用户时遇到了很多问题。当使用MySQL加载时,由于多个表之间存在大量连接,因此用户花费了大量时间。在加载数据后,我们看到了一个巨大的改进,特别是在加载数据时,因为大多数数据保存在单个文档中。
在缺点方面,就查询而言,couchbase似乎也有很多限制。 Couchbase替代SQL查询是视图。虽然我们设法使用map-reduce处理大多数查询,但我们真的很难弄清楚如何处理基于时间的查询。例如我们需要根据timestamp属性过滤用户。如果时间小于当前时间,我们只需要一个用户:
if(user.time < new Date().getTime() / 1000)
一旦用户的时间被设置为某个未来的时间,它就会被豁免于此视图,这是期望的行为,但它永远不会被添加回视图,除非我们更新它 - 文档只会被重新编入索引查看更新时间。
我们现在的解决方案是加载前x个用户文档,然后在我们的应用程序中检查时间。对user.time属性进行排序,以便我们获得那些时间小于或接近当前时间的用户。但我不确定这是否真的会在实时环境中起作用。理想情况下,我们希望在应用程序级别避免这些类型的检查。
也有时候例如当我们需要检查多个基于时间的属性时匹配。我们当前的策略在这种情况下不起作用,并且我们经常从视图中获取在应用程序中完成时未通过这些检查的文档。如果已经解决类似问题的人可以分享他们的经验,我将非常感激。提前谢谢。
更新
我们尝试使用仅适用于一个密钥的范围查询。就像我在大多数情况下所说的那样,我们有多个基于时间的键意味着多个范围不起作用。
答案 0 :(得分:6)
如果在视图函数中使用Date()。getTime(),您将始终获得该视图被编入索引的时间,正如您所说的“除非我们更新它,否则它永远不会被添加回视图”。
有两种方法:
糟糕的方式(不要在生产中这样做)。使用stale=false
参数查询视图。这将导致视图在返回结果之前更新。但是查看索引是一个缓慢的过程,特别是如果你有&gt; 1百万条记录。
好方法。使用范围请求。您只需要将map函数中的日期作为键或复杂键的一部分发出,并使用该范围请求。您可以看到一个示例here或here(如果您想在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);
}
}
现在要获取最近“更新”的文档,您需要使用params查询此视图:
startKey="dateTimeNowFromApp"
endKey="{}"
descending=true
请注意,startKey和endKey是交换的,因为我使用了降序。以下是有关couchbase支持的关键类型的documnetation链接。
此外,我找到了question的链接,也可以提供帮助。