field-value-query returning unexpected results when used with 'unfiltered' search in MarkLogic

65 Views Asked by At

I am getting false results with field-value-query when used with 'unfiltered' search.

I will explain the problem with sample data as given below.

XML:

<book>
    <name>Dixit</name>
    <age>25</age>
    <entry>
        <isbn>
            <type>hbk</type>
            <value>1234567</value>
        </isbn>
        <isbn>
            <type>pbk</type>
            <value>111111</value>
        </isbn>
    </entry>
    <entry>
        <isbn>
            <type>hbk</type>
            <value>1234567</value>
        </isbn>
        <isbn>
            <type>pbk</type>
            <value>222222</value>
        </isbn>
    </entry>
</book>

Above xml can have multiple <entry> elements. But two or more <entry> can't have same <type>.

I want all the entries having the combination of one or more isbn type, values.

As in the above example. I want <entry> having both hbk:1234567 AND pbk:111111

To achieve this I am running the below cts:query

cts:search(
  fn:doc()/book//entry,
  cts:and-query((
    cts:field-value-query("hbk", "1234567", ("case-insensitive")),
    cts:field-value-query("pbk", "222222", ("case-insensitive"))
  )),
  "unfiltered"
)

Output:

<entry>
    <isbn>
        <type>hbk</type>
        <value>1234567</value>
    </isbn>
    <isbn>
        <type>pbk</type>
        <value>111111</value>
    </isbn>
</entry>

According to me the the above output is wrong as it should return below <entry>.

<entry>
    <isbn>
        <type>hbk</type>
        <value>1234567</value>
    </isbn>
    <isbn>
        <type>pbk</type>
        <value>222222</value>
    </isbn>
</entry>

Even if I am running cts query with only one field-value-query as given below, getting the same result (entry having pbk value as 111111)

cts:search(
  fn:doc()/book//entry,
    cts:field-value-query("pbk", "222222", ("case-insensitive")),
  "unfiltered"
)

Fields I have created:

pbk : /book/entry/isbn[./type = 'pbk']/value

hbk : /book/entry/isbn[./type = 'hbk']/value

Index settings: (Same for both fields)

enter image description here

Note: For filtered search it is working fine.

Please help me to understand why this unexpected behaviour and what I can do to correct it.

Tried:

cts:search(
  fn:doc()/book//entry,
  cts:element-query(
    fn:QName('','isbn'),
    cts:and-query((
      cts:field-value-query("hbk", "1234567", ("case-insensitive")),
      cts:field-value-query("pbk", "222222", ("case-insensitive"))
    ))
  ),
  "unfiltered"
)
2

There are 2 best solutions below

4
David Ennis  -CleverLlamas.com On

Wrap your cts:and-query with a cts:element-query() on your isbn element. The below is an approximation of what I mean:

cts:search(
  fn:doc()/book//entry,
  cts:element-query(xs:QName("isbn"), 
      cts:and-query((
        cts:element-value-query(xs:QName("hbk"), "1234567", ("case-insensitive")),
        cts:element-value-query(xs:QName("pbk"), "222222", ("case-insensitive"))
      ))
   ),
  "unfiltered"
) 
1
David Ennis  -CleverLlamas.com On

Unfiltered returns the first element in the fragments that match. To get the result you want, you need to use filtered results or re-model your data or use fragment roots. Reverse the order of your elements and you will see - its always the first element in the searchable expression that is returned. That is the nature of fragments and filtered vs unfiltered.