Выражение пути в MarkLogic cts.search - PullRequest
4 голосов
/ 21 марта 2019

У меня сложилось впечатление, что XQuery и серверные JavaScript API в MarkLogic в значительной степени эквивалентны.Но, похоже, большая разница в cts:search против cts.searchcts:search я могу указать элемент для поиска и возврата.Например, я могу получить все рецепты, используя cinnaomon в качестве ингредиента из книги рецептов:

cts:search(//recipe, cts:element-word-query(xs:QName('ingredients'), 'cinnamon'))

Принимая во внимание, что cts.search не принимает выражение пути и возвращает весь документ книги рецептов:

cts.search(cts.elementWordQuery(xs.QName('ingredients'), 'cinnamon'))

Тот же вопрос был задан в списке рассылки MarkLogic, но я не вижу там ответа: https://developer.marklogic.com/pipermail/general/2015-March/016508.html

Ниже приведен минимальный пример:

<book>
  <recipe>
    <ingredients>cinnamon, peppermint</ingredients>
    <instruction/>
  </recipe>
  <recipe>
    <ingredients>sugar, peppermint</ingredients>
    <instruction/>
  </recipe>
  <recipe>
    <ingredients>coconut oil</ingredients>
    <instruction/>
  </recipe>
</book>

xquery будет:

cts:search(//recipe, cts:element-word-query(xs:QName('ingredients'), 'cinnamon'))

и ответ:

<recipe>
  <ingredients>cinnamon, peppermint</ingredients>
  <instruction></instruction>
</recipe>

Ответы [ 4 ]

5 голосов
/ 21 марта 2019

Есть технические причины, почему это так.Функция cts:search в XQuery на самом деле не функция, а специальная форма с синтаксисом функции.Это означает, что первый аргумент фактически не оценивается, а затем передается в функцию (если вы подумаете об этом, это будет очень неэффективный способ продолжить!).В Javascript функция cts.search является реальной функцией.Чтобы избежать неэффективности, мы пропустили первый параметр, поэтому вам нужно извлечь часть, которая вам нужна, из результата.

Если вы хотите ограничить набор результатов теми, которые находятся внутри элемента recipe, оберните ваш запрос cts:element-query(xs:QName("recipe"), $your-query)

3 голосов
/ 21 марта 2019

Это должно приблизить вас

https://docs.marklogic.com/cts.elementQuery

Применяется с cts.andQuery по мере необходимости.

В значительной степени верно, что интерфейсы JS и XQuery функционально эквивалентны, но есть несколько мест (это одно), где сам язык не поддерживает эквивалентность напрямую.Другой - последовательности XQuery, которые не имеют собственного эквивалента в JS - поэтому они предоставляются через дополнительные классы JS.

Любой cts (сложный) запрос может быть построен из примитивных объектов / методов запроса cts.Первый параметр в XQuery cts :: search () - это «доступное для поиска выражение», которое по сути совпадает с ограничивающей областью действия, и может быть объединено с cts.andQuery для получения одинакового эффекта (как в XQuery, так и в JS).В зависимости от того, какое именно выражение вы использовали в XQuery, вам нужно найти для него эквивалентный cts.query для JS (или xquery).

Следовательно, cts.elementQuery аналогичен cts :: search (// element).-имя, ..)

2 голосов
/ 23 марта 2019

Учитывая, что в javascript-версии cts: search () отсутствует первый параметр версии xquery - я не вижу, как он мог бы вернуть что-либо, кроме узлов документа. Оптимизация индексации, которую используют cts: search и cts.search, имеет гранулярность «фрагментов» (обычно документов), предназначенных для поиска нескольких подходящих документов потенциально неограниченного набора. Оттуда вам нужно пройти в структуру документа. XQuery особенно хорош в этом - обход пути является родным для языка, JavaScript не так уж и много.

Я предлагаю вам использовать search.search вместо cts: search - это высокоуровневый API, разработанный для упрощения таких задач.

1 голос
/ 25 марта 2019

Опираясь на ответ DALDEI, вы можете использовать API поиска, чтобы возвращать только элементы рецепта:

const search = require('/MarkLogic/appservices/search/search');

let options = fn.head(xdmp.unquote(`
<options xmlns="http://marklogic.com/appservices/search">
  <return-results>true</return-results>
  <searchable-expression>//recipe</searchable-expression>
  <extract-document-data>all</extract-document-data>
  <additional-query>
    <cts:element-word-query xmlns:cts="http://marklogic.com/cts">
      <cts:element>ingredients</cts:element>
      <cts:text xml:lang="en">cinnamon</cts:text>
    </cts:element-word-query>
  </additional-query>
</options>`)).root;

search.search("", options)        // returns a Sequence of search:response
  .toArray()[0]                   // get the first result
  .getElementsByTagName("recipe") // find all recipe elements 

Этот код возвращает NodeList элементов рецепта. Результатом для предоставленной вами книги будет следующий элемент:

<recipe xmlns:search="http://marklogic.com/appservices/search">
  <ingredients>cinnamon, peppermint</ingredients>
  <instruction/>
</recipe>

Это не очень хорошее решение (с точки зрения быстрой и простой), но оно может работать как обходной путь.

Я также пытался использовать функции jsearch , но не нашел способа передать параметр searchable-expression. Я мог пропустить это, потому что я еще не использовал это много.

Дополнительные показания:

Справочник параметров запроса поиск: поиск

...