【问题标题】:MarkLogic Wilcard Search - QConsole vs. Java APIMarkLogic 通配符搜索 - 控制台与 Java API
【发布时间】:2017-12-29 14:40:53
【问题描述】:

我相信我从基于 Java 的查询中看到了不同的结果,并且我相信查询控制台中的 cts:search 是等效的。这里有很多信息,我试图适当地组织它。以下是设置一个简单示例以复制我所看到的内容的步骤。

  1. 使用默认设置创建新数据库
  2. 使用默认设置添加新林
  3. 启用三字符搜索(仅限非默认数据库设置)
  4. 将下面三个json文档插入数据库中

查询控制台返回 doc2。 Java 客户端返回 doc2 AND doc1。为什么?我希望每个人都能得到相同的结果。我想用 Java 获取查询控制台返回的结果。我用 Java 写的查询定义不正确吗?

看起来 Java 客户端通配符搜索正在搜索整个文档,尽管我已指定我只想在给定的 json-property(名称)内进行通配符搜索。

在给定客户端 RawCombinedQueryDefinition 的情况下,是否有办法查看或记录生成的服务器端“cts 查询”?我想看看 Java 请求在服务器端被翻译成什么。

doc1.json

{
  "state": "OH",
  "city": "Dayton",
  "notes": "not Cincinnati"
}

doc2.json

{
  "state": "OH",
  "city": "Cincinnati",
  "notes": "real city"
}

doc3.json

{
  "state": "OH",
  "city": "Daytona",
  "notes": "this is a made up city"
}

查询用于插入文档的控制台代码

xquery version "1.0-ml"; 
xdmp:document-load("/some/path/doc1.json",
  <options xmlns="xdmp:document-load">
    <uri>/doc1.json</uri>
  </options>
); 

用于搜索的查询控制台代码

xquery version "1.0-ml";
cts:search(fn:collection(),
  cts:and-query((
    cts:json-property-value-query("state", "OH"),
    cts:json-property-value-query("city", "*Cincinnati*") 
  ))
)

Java QueryManager 以易于阅读的文本查询

{
  "search": {
    "query": {
      "queries": [
        {
          "value-query": {
            "type": "string",
            "json-property": "state",
            "text": "OH"
          }
        },
        {
          "value-query": {
            "type": "string",
            "json-property": "city",
            "text": "*Cincinnati*"
          }
        }
      ]
    }
  }
}

Java 代码

import com.marklogic.client.DatabaseClient;
import com.marklogic.client.DatabaseClientFactory;
import com.marklogic.client.document.DocumentPage;
import com.marklogic.client.document.DocumentRecord;
import com.marklogic.client.document.JSONDocumentManager;
import com.marklogic.client.io.Format;
import com.marklogic.client.io.StringHandle;
import com.marklogic.client.query.QueryManager;
import com.marklogic.client.query.RawCombinedQueryDefinition;
import org.junit.Test;

public class MarkLogicTest
{
    @Test
    public void testWildcardSearch()
    {
        DatabaseClientFactory.SecurityContext securityContext = new DatabaseClientFactory.DigestAuthContext("admin", "admin");
        DatabaseClient client = DatabaseClientFactory.newClient("localhost", 8000, "test", securityContext);
        QueryManager queryManager = client.newQueryManager();
        JSONDocumentManager documentManager = client.newJSONDocumentManager();

        String query = "{\n" +
                "  \"search\": {\n" +
                "    \"query\": {\n" +
                "      \"queries\": [\n" +
                "        {\n" +
                "          \"value-query\": {\n" +
                "            \"type\": \"string\",\n" +
                "            \"json-property\": \"state\",\n" +
                "            \"text\": \"OH\"\n" +
                "          }\n" +
                "        },\n" +
                "        {\n" +
                "          \"value-query\": {\n" +
                "            \"type\": \"string\",\n" +
                "            \"json-property\": \"city\",\n" +
                "            \"text\": \"*Cincinnati*\"\n" +
                "          }\n" +
                "        }\n" +
                "      ]\n" +
                "    }\n" +
                "  }\n" +
                "}";

        StringHandle queryHandle = new StringHandle(query).withFormat(Format.JSON);
        RawCombinedQueryDefinition queryDef = queryManager.newRawCombinedQueryDefinition(queryHandle);
        DocumentPage documents = documentManager.search(queryDef, 1);

        while (documents.hasNext())
        {
            DocumentRecord document = documents.next();
            StringHandle resultHandle = document.getContent(new StringHandle());
            String result = resultHandle.get();
            System.out.println(result);
        }
    }
}

System.out.println() 结果

{"state":"OH", "city":"Dayton", "notes":"not Cincinnati"} 
{"state":"OH", "city":"Cincinnati", "notes":"real city"}

为什么 Java 客户端返回 city = Dayton 的第一个结果?

提前致谢!

【问题讨论】:

    标签: java marklogic marklogic-9


    【解决方案1】:

    默认情况下,REST API 和 Java API 执行未经过滤的搜索(这意味着,匹配完全基于索引)。相比之下,cts:search() 默认执行过滤搜索(意味着检查结果文档以排除误报)。

    如果将“未过滤”选项添加到 cts:search(),它也会返回两个文档。

    快速解决方法是将“过滤”选项添加到 Java API 搜索,但更好的解决方法是优化索引以支持所需通配符查询的精确匹配。

    元素根据位置与通配符相关联。

    因此,对于这个查询,相信你需要开启元素词位置和三字符词位置的索引配置。

    希望对您有所帮助,

    【讨论】:

    • 感谢您快速且易于理解的回复。将过滤选项添加到 Java API 肯定是为了快速修复。我还在没有快速修复的情况下离开了查询,并打开了您提到的两个选项(元素词位置和三个字符词位置)。这也让我回到了我所期待的结果。当我完成我正在处理的 Java API 时,我将继续使用用于索引的数据库选项进行真正的微调。谢谢!
    【解决方案2】:

    通过快速查看上面的代码,您的 java 示例中没有 AND 查询。因此它是俄亥俄州或辛辛那提的一个或查询。

    【讨论】:

    • 感谢大卫的回复。我现在无法在 MarkLogic 文档中找到参考,但我相信“查询”数组中的任何子查询都是与在一起的。在我编写的所有代码中,它们的行为肯定是这样的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多