MarkLogic Wilcard搜索 - QConsole与Java API

时间:2017-12-29 14:40:54

标签: java marklogic marklogic-9

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

  1. 使用默认设置创建新数据库
  2. 使用默认设置添加新林
  3. 启用三个字符搜索(仅限非默认数据库设置)
  4. 将以下三个json文档插入数据库
  5. 查询控制台返回doc2。 Java客户端返回doc2 AND doc1。为什么?我希望每个人都能得到相同的结果。我想获得查询控制台返回的Java结果。我是否错误地用Java编写查询定义?

    看起来Java客户端通配符搜索正在搜索整个文档,即使我已经指定我只想在给定的json-property(name。)中进行通配符搜索。

    在给定客户端RawCombinedQueryDefinition的情况下,有没有办法查看或记录生成的服务器端“cts query”?我想看看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的第一个结果?

    提前致谢!

2 个答案:

答案 0 :(得分:4)

REST API以及Java API默认执行未过滤的搜索(意味着,匹配完全基于索引)。相比之下,cts:search()默认执行过滤搜索(意味着,检查结果文档会抛出误报)。

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

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

元素基于位置与通配符相关联。

因此,对于此查询,我认为您需要打开元素字位置和三个字符位置的索引配置。

希望有帮助,

答案 1 :(得分:0)

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