我们最近从关系(MySQL)转向NoSQL(couchbase)。基本上,它是社交手机游戏的后端。我们在扩展后端以处理越来越多的用户方面面临很多问题。使用MySQL加载时,用户花费大量时间,因为多个表之间存在大量联接。特别是在加载数据时,由于我们将大部分数据保存在单个文档中,因此在转入使用基准后,我们看到了巨大的改进。
不利的一面是,就查询而言,couchbase似乎也有很多限制。Couchbase替代SQL查询的是视图。尽管我们使用map-reduce设法处理了大多数查询,但我们确实很难弄清楚如何处理基于时间的查询。例如,我们需要根据时间戳属性过滤用户。如果时间小于当前时间,我们只需要一个用户即可:
if(user.time < new Date().getTime() / 1000)
发生的事情是,一旦将用户的时间设置为将来的某个时间,它便会从此视图中免除,这是期望的行为,但是除非我们对其进行更新,否则它永远不会添加回视图中-仅当文档的视图重新索引时,它才会在视图中重新索引更新。
现在,我们的解决方案是先加载x个用户文档,然后检查应用程序中的时间。排序是根据user.time属性完成的,因此我们可以得到时间少于或接近当前时间的那些用户。但是我不确定这是否可以在实际环境中正常工作。理想情况下,我们希望避免在应用程序级别进行此类检查。
当我们需要检查多个基于时间的属性时,有时也会进行匹配。我们当前的策略在这种情况下不起作用,并且我们经常从视图中获取无法在应用程序中通过这些检查的文档。如果有人已经解决了类似的问题,可以分享他们的经验,我将不胜感激。提前致谢。
更新:
我们尝试使用仅对一个键有效的范围查询。就像我说过的,在大多数情况下,我们有多个基于时间的键,这意味着无法使用多个范围。
如果在视图函数中使用Date()。getTime(),您将始终获得对该视图建立索引的时间,就像您所说的:“除非我们对其进行更新,否则它永远不会添加回视图中”。
有两种方法:
不好的方法(不要在生产中这样做)。使用stale=false
参数查询视图。这将导致视图在返回结果之前进行更新。但是视图索引编制是一个缓慢的过程,特别是如果您有> 1百万条记录。
好办法。使用范围请求。您只需要在地图功能中作为键或复杂键的一部分发出日期,然后使用该范围请求即可。您可以在此处或此处看到一个示例(同样,如果您想在沙发上使用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被交换了,因为我使用降序排列。这里也是一个链接documnetation有关couchbase支持的密钥类型。
另外,我还找到了一个对问题也有帮助的链接。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句