【问题标题】:Overcoming querying limitations in Couchbase克服 Couchbase 中的查询限制
【发布时间】:2013-09-16 20:50:55
【问题描述】:

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

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

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

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

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

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

更新:

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

【问题讨论】:

    标签: mapreduce nosql couchbase couchbase-view


    【解决方案1】:

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

    有两种方式:

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

    2. 好方法。使用范围请求。您只需要在 map 函数中发出您的日期作为键或复杂键的一部分并使用该范围请求。你可以看到一个例子 herehere (如果你想在 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 是交换的,因为我使用的是降序。这里还有一个指向 documnetation 的链接,了解 couchbase 支持的键类型。

    我还找到了一个指向 question 的链接,它也可以提供帮助。

    【讨论】:

    • 感谢您的详细回答。我们尝试使用 stale=false,但它只会重新索引更新的文档,因为它需要确保您获得最新的视图状态。它不会重新索引所有文档,这意味着我们仍然需要以某种方式更新文档。
    • 我们尝试使用仅适用于一个键的范围查询。就像我说的,在大多数情况下,我们有多个基于时间的键,这意味着多个范围不起作用。
    • 如果您的意思是多个时间范围,例如:1..250、600..900、2222..3333,您需要对每个范围执行一次视图查询。如果您需要使用startkey=[1, 50] endkey=[10,99] 按多个字段进行过滤(或者如果您想按一个字段排序并按另一个字段排序),您不能使用一个视图来执行此操作,因为 couchbase 视图只有一个索引。如果您遇到最后一种情况,您将需要在应用程序端执行部分计算。或者另一种方法是更改​​您的数据模型以避免这种情况。
    • 我的意思是按多个字段过滤。我们已经在应用程序中进行了这些检查,但是如果 couchbase 允许这些类型的查询会很好。也许我需要更改我的数据模型以在数据库级别处理此问题。感谢您的帮助:)
    • 你可以在这里找到一些解释 couchbase 如何以及为什么只有一个索引:couchbase.com/forums/thread/…(参见 FilipeManana 的帖子)。也许将来多个索引也会在 couchbase 中实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 2015-04-12
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    相关资源
    最近更新 更多