Marklogic query based on values of multiple attributes of the same element

倾然丶 夕夏残阳落幕 提交于 2019-12-23 12:14:00

问题


I have the following xmls:

sample1.xml <root> <subjectInfo> <subject id="001"/> <subject id="002" role="cross"/> </subjectInfo> </root>

sample2.xml <root> <subjectInfo> <subject id="002"/> <subject id="001" role="cross"/> </subjectInfo> </root>

I am searching for the documents where value of id attribute of subject is "001" but role(if it's there) of the same subject element is not "cross".So, In my example the result should contain sample1.xml and not sample2.xml

I thought the following query would do the job:

<code>
cts:search(/root,
        cts:near-query((
           cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001"),
           cts:not-query(cts:element-attribute-value-query(xs:QName("subject"),xs:QName("role"),"cross"))),0)

           )
</code>

But it does not(returns an empty sequence). Please give me one that does.


回答1:


As @wst said, the cts:not-query matches both documents. cts:* queries match document fragments, not subtrees. You can match the opposite of your conditions, by nesting the cts:element-attribute-value-query constructors inside of a cts:element-query. This will match sample2.xml:

cts:search(/root,
  cts:element-query(xs:QName("subject"),
    cts:and-query((
      cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001"),
      cts:element-attribute-value-query(xs:QName("subject"),xs:QName("role"),"cross")))))

Perhaps you can adjust your query requirements so this is sufficient. If not, you can exclude the documents that match this search, using the except operator. This will match sample1.xml:

cts:search(/root,
  cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001"))

except

cts:search(/root,
  cts:element-query(xs:QName("subject"),
    cts:and-query((
      cts:element-attribute-value-query(xs:QName("subject"),xs:QName("id"),"001"),
      cts:element-attribute-value-query(xs:QName("subject"),xs:QName("role"),"cross")))))

If your documents have unique identifiers, you could add range indices and use one of the cts:*-values functions to get the unique IDs for documents matching the second cts:search, and then use cts:not-query and cts:*-range-query to exclude the documents from the first cts:search.




回答2:


I think the problem is that the cts:not-query is matching on both documents, and therefore excludes them from the result set.

This may not be sufficient, since it's not an index-only query, but you could supplement the cts:search results by filtering out false positives:

cts:search(/root,
  cts:element-attribute-value-query(xs:QName("subject"), 
    xs:QName("id"), "001"))[subjectInfo/subject[@id='001' and not(@role='cross')]


来源:https://stackoverflow.com/questions/25624066/marklogic-query-based-on-values-of-multiple-attributes-of-the-same-element

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!