Исключение в базовом запросе с реляционным оператором в базе данных marklogic nosql в приложении Java

#java #xml #xpath #marklogic

#ява #xml — файл #xpath — путь #марклогик #java #xml #xpath #marklogic

Вопрос:

Я новичок в marklogic. Я пытаюсь выполнить простой запрос меньше / больше, чем с использованием базы данных nosql marklogic в приложении Java.

Java: v14 Marklogic: v9

Допустим, у меня есть база данных «user», и пример документа выглядит следующим образом:

 {
 "name": "some name",
 "dateOfBirth": "1991-07-01",
 ...
 ...
}
  

SQL-версия моего ожидаемого запроса является
выберите * у пользователя, где Дата рождения > «1980-01-01»

Использованный ниже код на Java

 StructuredQueryBuilder qb = new StructuredQueryBuilder();

StructuredQueryDefinition structuredQueryDefinition = qb.range(qb.pathIndex("/dateOfBirth"),
        "xs:string",
        (String[]) null,
        StructuredQueryBuilder.Operator.GT,
        eachCriteria.getValue());

markLogicTemplate.search(CombinedQueryDefinitionBuilder.combine(structuredQueryDefinition), User.class);
  

Создал индекс пути, используя приведенный ниже код:

 xquery version "1.0-ml";

  import module namespace admin = "http://marklogic.com/xdmp/admin"
      at "/MarkLogic/admin.xqy";

  let $config := admin:get-configuration()
  let $dbid := xdmp:database("user")
  let $pathspec := admin:database-range-path-index(
  $dbid,
  "string",
  "/dateOfBirth",
  "http://marklogic.com/collation/",
  fn:false(),
  "ignore")
  return
    admin:database-add-range-path-index($config, $dbid, $pathspec)
  

Получение исключения ниже в Java:

 com.marklogic.client.FailedRequestException: Local message: search failed: Bad Request. Server Message: XDMP-PATHRIDXNOTFOUND: cts:search(fn:collection(), cts:and-query((cts:collection-query("User"), cts:path-range-query("/dateOfBirth", ">", "1980-01-01", ("collation=http://marklogic.com/collation/"), 1)), ()), ("unfiltered", cts:score-order("descending")), xs:double("0"), ()) -- No string path range index for /dateOfBirth collation=http://marklogic.com/collation/
  

Пробовал повторно запустить сервер marklogic после создания индекса, но по-прежнему безуспешно.

Заранее спасибо за помощь.

Ответ №1:

Чтобы использовать индекс диапазона в запросе, индекс диапазона и запрос должны указывать

  • тот же тип данных
  • те же параметры сортировки для строкового типа данных

Я предполагаю, что типом данных должна быть дата для этого индекса диапазона и запроса (таким образом, большая дата соответствует, даже если строка меньше). Строковые значения в документах JSON могут быть проиндексированы как значения даты (и как многие другие типы данных).

В зависимости от ваших требований вы можете рассмотреть возможность индексирования документов с помощью TDE и проецирования строк из документов. Затем в Java API вы можете использовать RowManager для извлечения строк. Смотрите:

Надеюсь, это поможет,

Ответ №2:

Существуют фундаментальные проблемы с вышеупомянутым индексом диапазона и реализацией Java:

«/DateOfBirth» является W3C, не совместимым с XML /XPath. XML-документ должен иметь корневой элемент. Java API не вернет никакого результата с недопустимым XPath.

Мои образцы документов:

/person1.xml

 <person>
    <name>Alice Alice</name>
    <dob>1991-07-01</dob>
</person>
  

/person2.xml

 <person>
    <name>Lewis Carroll</name>
    <dob>1981-07-01</dob>
</person>
  

Вы можете создать либо date , либо string тип индекса диапазона в зависимости от потребностей приложения. query Обозначения Java должны соответствовать стандарту MarkLogic Java API.

Решение первое: я создаю string индекс диапазона путей -> /person/dob

Java code :

 StructuredQueryDefinition queryDef = sqb.range(sqb.pathIndex("/person/dob"), "xs:string", Operator.GT, "1980-01-01");
  

Ведение журнала Java:

 Query result: 

<search:response snippet-format="snippet" total="2" start="1" page-length="10" xmlns:search="http://marklogic.com/appservices/search">
  <search:result index="1" uri="/person1.xml" path="fn:doc(amp;quot;/person1.xmlamp;quot;)" score="0" confidence="0" fitness="0" href="/v1/documents?uri=/person1.xml" mimetype="application/xml" format="xml">
    <search:snippet>
      <search:match path="fn:doc(amp;quot;/person1.xmlamp;quot;)/person/dob"><search:highlight>1991-07-01</search:highlight></search:match>
    </search:snippet>
  </search:result>
  <search:result index="2" uri="/person2.xml" path="fn:doc(amp;quot;/person2.xmlamp;quot;)" score="0" confidence="0" fitness="0" href="/v1/documents?uri=/person2.xml" mimetype="application/xml" format="xml">
    <search:snippet>
      <search:match path="fn:doc(amp;quot;/person2.xmlamp;quot;)/person/dob"><search:highlight>1981-07-01</search:highlight></search:match>
    </search:snippet>
  </search:result>
...............
</search:response>

Session completed: 2020-09-07T15:49:26.409488
  

Решение второе: я создаю date индекс диапазона путей -> /person/dob

Java API выдает тот же результат в этом сценарии.

Java code :

 StructuredQueryDefinition queryDef = sqb.range(sqb.pathIndex("/person/dob"), "xs:date", Operator.GT, "1980-01-01");
  

Вы всегда можете использовать другие query конструкции для достижения желаемых результатов.