【问题标题】:Cloudant With Lucene Search Fails To Sort As Expected带有 Lucene 搜索的 Cloudant 无法按预期排序
【发布时间】:2018-03-17 09:50:47
【问题描述】:

我对 Cloudant 还很陌生,但在 DB2 上使用 SQL 开发已经有一段时间了。我遇到了一个问题,我认为我正在使用 Lucene 查询引擎和 Cloudant 索引从我的查询中返回结果。查询得到了我想要的所有结果,但是它们没有正确排序。我想根据“officialName”字段按字母顺序对结果进行排序。因为我们只返回 n 个结果中的前 21 个(然后我们有一个 js 处理程序通过分页调用更多结果),所以我们无法在 java 端进行排序,而必须通过 Cloudant 进行排序。我们的应用程序正在运行 Java,并使用 IBM 的 Bluemix 和 WebSphere Liberty Profile 执行。我已经打包了 cloudant-client-2.8.0.jar 和 cloudant-HTTP-2.8.0.jar 文件来访问 Cloudant 数据库。我们有许多正在运行的查询,因此连接本身很好。

以下是构建 Cloudant 客户端搜索对象的代码:

Search search = getCloudantDbForOurApp().search("bySearchPP-ddoc/bySearchPP-indx").includeDocs(true);
SearchResult<DeliverableDetails> result = search.sort(getSortJsonString(searchString)).querySearchResult(getSearchQuery(searchString), DeliverableDetails.class);

这里是getSortJsonString方法。应该注意的是,搜索字符串通常不为空。我还应该注意,保留或删除 -score 属性确实会影响搜索,但永远不会达到 alpha 排序结果。

private String getSortJsonString(String searchString) {
    String sortJson;
    if (searchString != null && !searchString.isEmpty()) {
        sortJson = "[\"-<score>\",\"officialName<string>\"]";
    } else {
        sortJson = "\"officialName<string>\"";
    }
    return sortJson;
}

这里是getSearchQuery方法的相关代码供参考:

...
query += "(";
query += "officialName:" + searchString + "^3";
query += " OR " + "deliverableName:" + searchString + "^3";
query += " OR " + "alias:" + searchString + "^3";
query += " OR " + "contact:" + searchString;
query += ")";
....
// The query will look like below, where<search_string> is some user inputted value
// (officialName:<search_string>*^3 OR deliverableName:<search_string>*^3 OR alias:<search_string>*^3 OR contact:<search_string>*)

我已经使用 Cloudant 仪表板设置了一个设计文档和索引,如下所示:

{
"_id": "_design/bySearchPP-ddoc",
"_rev": "4-a91fc4ddeccc998c58adb487a121c168",
"views": {},
"language": "javascript",
"indexes": {
  "bySearchPP-indx": {
    "analyzer": {
      "name": "perfield",
      "default": "standard",
      "fields": {
        "alias": "simple",
        "contact": "simple",
        "deploymentTarget": "keyword",
        "businessUnit": "keyword",
        "division": "keyword",
        "officialName": "simple",
        "deliverableName": "simple",
        "pid": "keyword"
      }
    },
    "index": "function(doc) {
              if (doc.docType === \"Page\") {
                index(\"officialName\", doc.officialName, {\"store\":true, \"boost\":4.0});
                index(\"deliverableName\", doc.deliverableName, {\"store\":true, \"boost\":3.0});
                if (doc.aliases) {
                  for (var i in doc.aliases) {
                    index(\"alias\", doc.aliases[i], {\"store\":true, \"boost\":2.0});
                  }
                }
                if (doc.allContacts) {
                  for (var j in doc.allContacts) {
                    index(\"contact\", doc.allContacts[j], {\"store\":true, \"boost\":0.5});
                    }
                }
                index(\"deploymentTarget\", doc.deploymentTarget, {\"store\":true});
                index(\"businessUnit\", doc.businessUnit, {\"store\":true});
                index(\"division\", doc.division, {\"store\":true});
                index(\"pid\", doc.pid.toLowerCase(), {\"store\":true});
             }
          }"
     }
   }
 }

我不确定排序是否正常工作,只是没有按照我想要的方式工作,或者我是否配置错误。无论哪种方式,任何帮助都将不胜感激。 -道格

【问题讨论】:

  • 在一种情况下,您首先按分数排序,然后按官方名称排序。这不是问题吗?
  • 您可以查看SearchResultRow 上的订单以查看排序中使用的值。数组中每一行的第一个值对应于排序中使用的第一个值。 for (对象 obj : row.getOrder()) { System.out.println(obj); }
  • @markwatsonatx - 无论我是否取出分数标签,它都不起作用。感谢他的调试提示。这表明没有返回 officialName 值。做了一些挖掘,我发现该字段已编入索引但不应该被标记化。当我将索引表单简单分析器更改为关键字时,它起作用了!感谢您的提示。

标签: java sorting lucene cloudant


【解决方案1】:

在上面 cmets 的帮助下解决了我自己的问题。显然一切都设置正确,但是一旦我按照@markwatsonatx 进行调试,我就可以看到我想要的字段没有被返回。是否在网上进行了一些挖掘,显然是为了排序,该字段必须既被索引又未被标记。因此,我检查了我的索引并注意到该字段正在由 Simple 分析器进行分析。将其更改为关键字,排序按预期工作。希望这可以帮助某人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多