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

Querying multiple fields at a time on a view

我有一个场景,在我的应用程序中,用户将按搜索条件(比如字段 1、字段 2、字段 3(字段 3 是日期范围))进行搜索。 字段 1 是强制性搜索条件,但字段 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 的新手,并且根据我有限的知识,我知道 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]);
  }
}

索引构建良好。

但问题出在"querying"这个索引上,比如说我有多个搜索条件的情况(即用户可以提供其中一个或它们的组合),查询是不可能的通过 key/keys。否则我能找到的选项是 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.

谢谢。

所以,对你的问题的简短回答是 "this is the incorrect approach." 让我详细说明一下,首先提供一些背景知识,然后为你指明正确的方向。

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

my application a user will be searching by search criterias

因此,这导致 Couchbase 可能不适用于您的场景。我说 可能 是因为 Couchbase 通常在几乎任何情况下都表现良好,但您可能需要一些技巧(技术术语)才能到达那里。

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

因此,你确实面临着另辟蹊径的前景。以下是一些可能的替代方案:

  1. 使用SQL数据库:这个选项是不言自明的。您了解 SQL.

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

    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:这是一种建立在Couchbase之上的基于sql的查询语言。在引擎盖下,它执行类似于选项 2 的操作,但为您完成所有操作。

  2. 使用 Elasticsearch: this is one of the best full-text search noSql data stores out there. It is architeched very similar to Couchbase, except instead of memory-based access, Elasticsearch uses Lucene indexing to achieve very fast full-text search. Use this where you have complex, multi-property documents that you want high-performing searches for a limitless set of queries. Couchbase even has a plugin 将数据转储到 Elasticsearch 集群,这样您就可以轻松获得两个平台的优势。

选项 4 在任何情况下都可能是您的最佳选择,但您需要权衡具体用例的利弊以确定最佳前进路径。