1

Search Developers Guideによると:各制約には名前が付けられており、その名前はオプションノードのすべての演算子と制約で一意である必要があります。

次のような出力を生成するコンテンツエンリッチメントパッケージを使用しています。

`<TM360:Measurements Measurements="Distance">
    <Measurements:Distance Amount="3" Unit="inches"/>
</TM360:Measurements>
<TM360:Measurements Measurements="Volume">
    <Measurements:Volume Amount="5.0" Unit="liters"/>
</TM360:Measurements>`

「金額」を見る:属性localNameは一意ではありませんが、それを含む要素は一意です。

制約名の一意性の制限を回避して、上記の両方のエントリのインデックスを含む「金額:5.0」などの制約付き検索を作成する方法はありますか?

この状況に対処するための最良の方法は何ですか?

4

3 に答える 3

2

これを実現するためのカスタム制約を作成できます。次の 3 つのスクリプトを使用してこれを行うことに成功しました。

  • セットアップ db.xqy
  • 検索.xqy
  • カスタム制約.xqy

2 つの "Amount" 範囲インデックスを作成し、いくつかのサンプル ドキュメント (test1.xml と test2.xml) を追加するセットアップ スクリプトを次に示します。

xquery version "1.0-ml";

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

declare namespace TM360        = "http://example.com/TM360";
declare namespace Measurements = "http://example.com/Measurements";

declare function local:make-amount-index($parent-name) {
  admin:database-range-element-attribute-index(
    (: data type       :) "decimal",
    (: parent name     :) "http://example.com/Measurements",$parent-name,
    (: attribute name  :) "", "Amount",
    (: collation       :) "",
    (: value positions :) false()
  )
};

(: Set up the indexes (or you can add these via the Admin UI) :)
let $dbid       := xdmp:database(),
    $rangespec1 := local:make-amount-index("Distance"),
    $rangespec2 := local:make-amount-index("Volume"),
    $config     := admin:get-configuration(),
    $config     := admin:database-add-range-element-attribute-index($config, $dbid, $rangespec1),
    $config     := admin:database-add-range-element-attribute-index($config, $dbid, $rangespec2)
return
  admin:save-configuration($config)

,

(: Add some sample docs :)
xdmp:document-insert("/test1.xml",
  <TM360:Measurements Measurements="Distance">
      <Measurements:Distance Amount="3" Unit="inches"/>
  </TM360:Measurements>),

xdmp:document-insert("/test2.xml",
  <TM360:Measurements Measurements="Volume">
      <Measurements:Volume Amount="5.0" Unit="liters"/>
  </TM360:Measurements>)

以下は、2 つの検索を行う search.xqy です。

  • search:search("Amount:3",$options)
  • search:search("Amount:5",$options)

特に、カスタム制約を定義する $options ノードに注意してください。

xquery version "1.0-ml";

import module namespace search="http://marklogic.com/appservices/search"
       at "/MarkLogic/appservices/search/search.xqy";

declare variable $options :=
  <options xmlns="http://marklogic.com/appservices/search">
    <constraint name="Amount">
      <custom facet="false">
        <parse apply="parse-amount"
               ns="http://example.com/custom-constraint"
               at="/custom-constraint/custom-constraint.xqy">
        </parse>
      </custom>
    </constraint>
  </options>;

(: matches test1.xml :)
search:search("Amount:3",$options),

(: matches test2.xml :)
search:search("Amount:5",$options)

最後に、custom-constraint.xqy コードを示します。これは、制約テキストを 2 つの Amount インデックスにわたる cts OR クエリに変換するものです。

xquery version "1.0-ml";

module namespace my = "http://example.com/custom-constraint";

declare namespace Measurements = "http://example.com/Measurements";

declare default function namespace "http://www.w3.org/2005/xpath-functions";

(: Convert the constraint text into an OR query against "Distance" and "Volume" :)
declare function my:parse-amount($constraint-qtext as xs:string,
                                 $right as schema-element(cts:query))
        as schema-element(cts:query)
{
  let $value := xs:decimal($right//cts:text)
  return
    <cts:or-query>{
      my:make-amount-query("Distance",$value),
      my:make-amount-query("Volume"  ,$value)
    }</cts:or-query>
};


declare function my:make-amount-query($parent-name, $value) {
  cts:element-attribute-range-query(
    (: parent name    :) QName("http://example.com/Measurements", $parent-name),
    (: attribute name :) xs:QName("Amount"),
    (: operator       :) "=",
    (: value          :) $value
  )
};

制約をファセットとしても機能させたい場合は、さらに start-facet 関数と finish-facet 関数を実装する必要があります (それに応じて、オプション ノードの定義を拡張します。検索開発者ガイドには、方法の例が含まれています。これを行う。

于 2011-11-10T18:16:39.177 に答える
2

最良の結果を得るには、その XML をリファクタリングまたは強化する必要があります。検索 API は、QName に基づく MarkLogic のインデックス作成機能を最大限に活用するように設計されています。現在使用している XML には、1 つの要素 QName (TM360) といくつかの属性 QName がありますが、いずれも厳密に選択的ではありません。

XSLT または再帰変換を使用して、その XML を再フォーマットできます。次のようなものをターゲットにすることをお勧めします。

<dist:inches xmlns:dist="ns://fubar.distance">3</dist:inches>
<vol:liters xmlns:vol="ns://fubar.volume">5.0</vol:liters>

副作用として、これにより、より簡潔な XPath クエリを記述できるようになり、ノードに対してより具体的なスキーマ タイプを使用できるようになります。

この使用例はおそらく不自然ですが、比較を容易にするために、これらすべての測定値をhttp://en.wikipedia.org/wiki/Cgsなどの SI 単位の標準サブセットに正規化することを検討することもできます。

于 2011-11-10T16:50:52.007 に答える
1

cts 関数を使えば比較的簡単です。次のようなことができます。

declare namespace Measurements = "http://example.com/Measurements";

cts:search(doc(), cts:element-attribute-value-query(
  (xs:QName("Measures:Distance"), xs:QName("Measures:Volume")),
  xs:QName("Amount"),
  $myamount
))

幸いなことに、MarkLogic 8.0-5 の時点でそれを単一の検索制約として表現し、それをsearch:search(最近の) 組み込み REST API で使用することもできます。

xquery version "1.0-ml";

declare namespace TM360        = "http://example.com/TM360";
declare namespace Measurements = "http://example.com/Measurements";

xdmp:document-insert(
  "/amount3.xml",
  <TM360:Measurements Measurements="Distance">
    <Measurements:Distance Amount="3" Unit="inches"/>
  </TM360:Measurements>
),
xdmp:document-insert(
  "/amount5.xml",
  <TM360:Measurements Measurements="Volume">
    <Measurements:Volume Amount="5.0" Unit="liters"/>
  </TM360:Measurements>
)

;

import module namespace search="http://marklogic.com/appservices/search"
       at "/MarkLogic/appservices/search/search.xqy";

declare variable $options :=
  <options xmlns="http://marklogic.com/appservices/search">
    <constraint name="Amount">
      <value>
        <element ns="http://example.com/Measurements" name="Distance"/>
        <element ns="http://example.com/Measurements" name="Volume"/>
        <attribute ns="" name="Amount"/>
      </value>
    </constraint>
  </options>;

(: matches /amount3.xml :)
search:search("Amount:3",$options),

(: matches /amount5.xml :)
search:search("Amount:5.0",$options)

すべての要素と属性の組み合わせに範囲インデックスがある場合は、Evan が提案するように、範囲制約を使用することもできます..

チッ!

于 2011-11-10T19:51:52.213 に答える