克服Couchbase中的查询限制

uma*_*air 2 mapreduce nosql couchbase couchbase-view

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

在缺点方面,就查询而言,couchbase似乎也有很多限制.Couchbase替代SQL查询是视图.虽然我们设法使用map-reduce处理大多数查询,但我们真的很难弄清楚如何处理基于时间的查询.例如,我们需要根据timestamp属性过滤用户.如果时间少于当前时间,我们只需要一个用户:

if(user.time < new Date().getTime() / 1000)
Run Code Online (Sandbox Code Playgroud)

会发生的情况是,一旦将用户的时间设置为某个未来的时间,它就会被豁免于此视图,这是期望的行为,但除非我们更新它,否则它永远不会被添加回视图 - 文档仅在其视图中被重新编入索引时更新.

我们现在的解决方案是加载前x个用户文档,然后在我们的应用程序中检查时间.对user.time属性进行排序,以便我们获得那些时间小于或接近当前时间的用户.但我不确定这是否真的会在实时环境中起作用.理想情况下,我们希望在应用程序级别避免这些类型的检查.

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

更新:

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

m03*_*eek 6

如果你在一个视图函数中使用Date().getTime(),你将总是得到索引该视图的时间,正如你所说的"它永远不会被添加回视图,除非我们更新它".

有两种方法:

  1. 糟糕的方式(不要在生产中这样做).使用stale=falseparam 查询视图.这将导致视图在返回结果之前更新.但是视图索引是一个缓慢的过程,特别是如果你有> 1毫安的记录.

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

即你会有像这样的文档:

doc = {
 "id"=1,
 "type"="doctype",
 "timestamp"=123456, //document update or creation time
 "data"="lalala"
}
Run Code Online (Sandbox Code Playgroud)

对于那些docs map函数将如下所示:

map = function(){
 if (doc.type === "doctype"){
  emit(doc.timestamp,null);
 }
}
Run Code Online (Sandbox Code Playgroud)

现在要获得最近"更新"的文档,您需要使用params查询此视图:

startKey="dateTimeNowFromApp" 
endKey="{}"
descending=true
Run Code Online (Sandbox Code Playgroud)

请注意,startKey和endKey是交换的,因为我使用了降序.这里也是一个链接documnetation有关couchbase支持的密钥类型.

我也找到了一个可以提供帮助的问题的链接.