在视图上一次查询多个字段

时间:2015-01-31 21:34:35

标签: couchbase

我有一个场景,其中在我的应用程序中,用户将按搜索标准进行搜索(例如field1,field2,field3(字段3是日期范围))。 Field1是强制搜索条件,但字段2 ... 5是可选的,它们可以通过用户输入组合。

所以我创建了一个发出多个键的视图(用户可以搜索的所有可能组合)。

例如:

function (doc, meta) {
if(doc.eventType=='myEvent' && doc.field1){
  if(doc.field2) {
  emit([doc.field1,doc.field2]);
  }
  if(doc.field3) {
  emit(doc.field1,doc.field3]);
  }
  if(doc.field4) {
  emit([doc.field1,doc.field4]);
  }
  if(doc.field5) {
  emit([doc.field1,doc.field5]);
  }
  if(doc.field2 && doc.field3) {
  emit([doc.field1,doc.field2,doc.field3]);
  }
  if(doc.field2 && doc.field4) {
  emit([doc.field1,doc.field2,doc.field4]);
  }
  if(doc.field2 && doc.field5) {
  emit([doc.field1,doc.field2,doc.field5]);
  }
  if(doc.field3 && doc.field4) {
  emit([doc.field1,doc.field3,doc.field4]);
  }
  if(doc.field3 && doc.field5) {
  emit([doc.field1,doc.field3,doc.field5]);
  }
  if(doc.field4 && doc.field5) {
  emit([doc.field1,doc.field4,doc.field5]);
  }
  if(doc.field2 && doc.field3 && doc.field4) {
  emit([doc.field2,doc.field3,doc.field4]);
  }
  if(doc.field2 && doc.field3 && doc.field5) {
  emit([doc.field1,doc.field2,doc.field3,doc.field5]);
  }
  if(doc.field2 && doc.field4 && doc.field5) {
  emit([doc.field1,doc.field2,doc.field4,doc.field5]);
  }
  if(doc.field3 && doc.field4 && doc.field5) {
  emit([doc.field1,doc.field3,doc.field4,doc.field5]);
  }
  if(doc.field2 && doc.field3 && doc.field4 *&& doc.field5) {
  emit([doc.field1,doc.field2,doc.field3,doc.field4,doc.field5]);
  }
}
}

这是正确的方法还是我在这里遗漏了一些东西,因为生成的索引值将是多余的,索引文件大小会呈指数级增长。

因为我'我是Couchbase的新手,根据我的有限知识,我了解沙发基地不允许在查询中搜索空值? 例如,我无法使用单个发射来实现上述目标:

function (doc, meta) {
if(doc.eventType=='myEvent' && doc.field1){
if(doc.field2 && doc.field3 && doc.field4 *&& doc.field5 {
  emit([doc.field1,doc.field2,doc.field3,doc.field4,doc.field5]);
  }
}

索引构建正常。

但问题在于"查询"该索引,例如对于其中我具有如上所述的多个搜索标准的场景(即,用户可以提供它们中的一个或它们的组合),通过键/键不可能进行查询。另外我可以找到的选项是N1QL,它似乎仍然处于开发人员预览状态,所以我认为它不是生产就绪。

还有其他更好的方法来进行这样的搜索和检索,因为这是一个非常常见的用例,而且我来自一个关系数据库世界,我发现很难得到这个概念,或者我不是确定如果我在这里遗漏了什么,请帮助我,我正在寻找的是一个单一视图的SQL查询,如:

- where子句中提供的字段可能包含1个或多个值。或者他们可能是空的。这纯粹基于最终用户输入的搜索条件

select * from view_name where doc.field1="x" and doc.field2 in ("y","z","d") and doc.field3 in ("abc") and Date_column between 2011/02/25 and 2011/02/27 sort by Date_Column desc;

是否可以使用沙发基础视图和沙发基础客户端java api进行上述查询和检索。

感谢。

1 个答案:

答案 0 :(得分:1)

所以,对你的问题的简短回答是"这是不正确的方法。"让我详细说明这一点,首先给出一些背景,然后指出你正确的方向。

首先,应该理解Couchbase被设计成一个非常高性能的存储和检索引擎。它不是一个高度可搜索的全文数据库。在你的第一句话中,你说

  

我的应用程序用户将按搜索标准进行搜索

因此,这导致人们认为Couchbase可能不适合您的场景。我说可能因为Couchbase在任何情况下通常都表现良好,但可能需要一些指导(技术术语)来实现目标。

您明确指出,您采用的方法不可扩展(在数据中发出可能值的每种组合)。我会更进一步。 它不仅不具备可扩展性,而且您实际上将使用Couchbase的性能最差的功能来满足您的应用程序的需求。 Couchbase索引是基于磁盘的,虽然它们很快,但它们确实很快不共享由Couchbase中的memcached支持的vBucket存储机制提供的基于内存的多节点访问,它们也不提供主要Couchbase平台的即时一致性或任何其他有用功能。

因此,你确实面临着选择另一条道路的前景。以下是一些可能的替代方案:

  1. 使用SQL数据库:此选项不言自明。您将获得SQL的优点和缺点。

  2. Application-side Joins :使用这种方法,您的应用程序可以容忍过时的索引并且只能在搜索中获得合理的最新结果(合理的是1-5分钟) ,平均最坏情况)。您为感兴趣的每个字段创建单独的索引。然后,当查询出现时,您将查找数据抽象层中索引之间的交叉点。例如,

  3.     select * from view_name 
        where doc.field1="x"
          and doc.field2 in ("y","z","d") 
          and doc.field3 in ("abc") 
          and Date_column between 2011/02/25 and 2011/02/27
        sort by Date_Column desc;
    

    这实际上需要四个独立的指数。在您的应用程序中,首先搜索最严格的索引,然后查看剩余索引以构建结果集,最后对输出进行排序并发送到客户端。你完成了SQL数据库通常会做的工作,但是你正在使用Couchbase,因此速度非常快,而且你不会得到SQL数据库给你的任何神奇的垃圾。

    1. 使用N1QL这是一种基于sql的查询语言,构建于Couchbase之上。在引擎盖下,它会执行类似于选项2的操作,但会为您完成所有操作。

    2. 使用Elasticsearch这是最好的全文搜索noSql数据存储之一。它的架构非常类似于Couchbase,除了基于内存的访问,Elasticsearch使用Lucene索引来实现非常快速的全文搜索。如果您有复杂的多属性文档,希望对无限的查询集进行高性能搜索,请使用此选项。 Couchbase甚至有plugin将数据转储到Elasticsearch集群,因此您可以轻松地获得两个平台的优势。

    3. 在任何情况下,选项4可能是您的最佳选择,但您需要权衡特定用例的优缺点,以确定最佳前进路径。