【问题标题】:Restricting range index on elements within documents in a specific collection限制特定集合中文档内元素的范围索引
【发布时间】:2017-02-20 17:34:39
【问题描述】:

我们正在构建一个以 ML 作为后端的企业应用程序。应用程序中的许多屏幕都有下拉菜单,需要文档内元素的不同值。因此,我们为这些元素创建了元素范围索引,并准备好使用范围索引获取不同值的代码。

现在我们在逻辑上将文档分离到不同的集合中 - 例如“basedata”集合保存所有应用程序基础数据文档和“transactiondata”集合保存所有传入/传出到我们应用程序的事务。

现在的要求是将范围索引限制为仅基础数据收集文档,而不是事务数据文档。

例如:如果我们有 localname="entityName" 的元素范围索引,我们不希望为文档中存在的 entityName 值构建范围索引交易数据收集。我们希望“entityName”的不同值仅出现在附加到基础数据集合的文档中。

我们如何才能做到这一点?

编辑:

感谢大卫和 grtjn。

这就是我们目前在 java 层中所做的事情:下面的代码正确地返回了字段 entityName 的不同名称,该字段创建了一个范围索引。

String valueOptionString = 
    " <search:options xmlns:search="http://marklogic.com/appservices/search">
        <search:values name="entityName">
            <search:range type="xs:string">
                <search:element name="entityName">
                </search:element>
            </search:range>
        </search:values>
    </search:options> ";    

QueryManager queryMgr = client.newQueryManager();
    QueryOptionsManager optionsMgr = client.newServerConfigManager().newQueryOptionsManager();
    optionsMgr.writeOptions("DistinctValues", new StringHandle(valueOptionString));

    ValuesDefinition vdef = queryMgr.newValuesDefinition("entityName", "DistinctValues");
    ValuesHandle vh = queryMgr.values(vdef, new ValuesHandle());

    for (CountedDistinctValue value : vh.getValues()) {
        System.out.println("Distinct value is :: " +
            value.get("xs:string", String.class));
    }

如您所见,我没有在 queryMgr.values() 的任何位置设置集合;根据提供的建议,我尝试将集合约束添加到 valueOptionString 中,但它不起作用。 这是正确的方法吗?有没有其他出路

<search:options xmlns:search="http://marklogic.com/appservices/search">
<search:values name="createdBy">
    <search:range type="xs:string">
        <search:element name="createdBy"/>
    </search:range>
    <search:collection>
        <search:uri>basedaata</search:uri>
        <search:uri>tansactiondata</search:uri>
    </search:collection>
</search:values>
</search:options>

遇到错误:

Local message: /config/query write failed: Bad Request. Server Message: RESTAPI-INVALIDCONTENT: (err:FOER0000) Invalid content: Op
eration results in invalid Options: XDMP-VALIDATEUNEXPECTED: (err:XQDY0027) validate strict { $opt } -- Invalid node: Found text{"basedaata..."} but expected () at fn:doc("")

编辑 2:

根据以下答案,我更新了我的代码,在可选查询中包含“附加查询”部分,以包含返回的不同值。但是,它看起来附加查询部分被忽略并且没有按预期工作

更新了可选查询:

 <search:options xmlns:search="http://marklogic.com/appservices/search">
    <search:values name="entityName">
        <search:range type="xs:string">
            <search:element name="entityName"/>
        </search:range>
    </search:values>
    <search:additional-query>
        <cts:collection-query xmlns:cts="http://marklogic.com/cts">
            <cts:uri>basedata</cts:uri>
            <cts:uri>DistinctValueTest</cts:uri>
        </cts:collection-query>
    </search:additional-query>
</search:options>

以下是我的文件。我也有字段 entityName 的元素范围索引..

基础数据集合中的文档:

<?xml  version="1.0" encoding="UTF-8"?>
<entity>
    <entityName>Company</entityName>
    <createdBy>CompanyOwner</createdBy>
    <createdDate>2017-01-01T05:56:35.360Z</createdDate>
    <status>Active</status>
    <entityattributes>
        <entityattribute>
        </entityattribute>
    </entityattributes>
</entity>

现在创建了一个名为 DistinctValueTest 的测试集合,并在该集合中添加了一个用于测试目的的文档。

DistinctValueTest 集合中的文档:

<?xml  version="1.0" encoding="UTF-8"?>
<entity>
    <entityName>DistinctValueTestEntity</entityName>
    <createdBy>DistinctValuteSystemNew</createdBy>
    <createdDate>2017-01-03T05:56:35.360Z</createdDate>
    <status>Active</status>
    <entityattributes>
        <entityattribute>
        </entityattribute>
    </entityattributes>
</entity>

程序的输出是:Company,DistinctValueteSystemNew 当两个集合都在附加查询部分中提供时

<cts:collection-query xmlns:cts="http://marklogic.com/cts">
    <cts:uri>basedata</cts:uri>
    <cts:uri>DistinctValueTest</cts:uri>
 </cts:collection-query

但是,如果我只在 cts:uri 中提供“basedata”集合,它仍将输出显示为 Company,DistinctValueteSystemNew ,而不仅仅是 Company

 <cts:collection-query xmlns:cts="http://marklogic.com/cts">
     <cts:uri>basedata</cts:uri>
 </cts:collection-query

【问题讨论】:

  • 将编辑部分放在一个单独的问题中可能会更好..

标签: marklogic marklogic-8


【解决方案1】:

您不是为每个条件组合构建多个索引,而是在读取时组合索引。 cts:values 函数采用第 4 个参数,该参数表示一个查询,该查询将修剪从中派生值的片段。在您的情况下,它看起来像:

cts:values(
  cts:element-reference(xs:QName("entityName")),
  (),
  (),
  cts:collection-query("basedata")
)

使用稍微抽象一点的search:values 函数和/v1/values REST 端点可以实现类似的效果。

HTH!

【讨论】:

  • 感谢大卫/grtjn。我尝试了上述方法,并用我遇到的问题更新了我的问题。请告诉我。提前致谢。
【解决方案2】:

基于 grtjn 的回答和您更新的问题,将返回的值限制为特定集合的一种直接方法是将 additional-query 添加到您的选项中。

<search:options xmlns:search="http://marklogic.com/appservices/search">
  <search:values name="createdBy">
    <search:range type="xs:string"> 
      <search:element name="createdBy"/>
    </search:range>
  </search:values>
  <search:additional-query>
    <cts:collection-query xmlns:cts="http://marklogic.com/cts">
      <cts:uri>basedata</cts:uri>
      <cts:uri>transactiondata</cts:uri>
    </cts:collection-query>
  </search:additional-query>
</search:options>

additional-query 会添加到使用该组选项运行的每个查询中。

【讨论】:

  • 附加查询是处理此问题的一种方法,但您的 Java 代码将在幕后调用 /v1/values/createdBy。该 REST 端点将接受一个collection 请求参数、一个q 参数和一个structuredQuery 参数,所有这些都可以用于获得与附加查询相同的效果,但以更动态的方式。应该有办法告诉queryMgr 对象通过额外的约束。 (周围的人可能知道怎么做?)
  • @grtjn 未按预期工作。更新了我原来的问题。请检查编辑 2。
  • @Dave 对我在上述问题的编辑 2 中面临的问题有任何更新吗?感谢您的帮助。
猜你喜欢
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多