#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
конструкции для достижения желаемых результатов.