Skip to main content

What's New in MarkLogic 11

JSON Property Scope and Container Queries Match Array Items Differently

In MarkLogic 8, the query constructed by the XQuery function cts:json-property-scope-query and the Server-Side JavaScript function cts.jsonPropertyScopeQuery matched if its criteria query matched anywhere within the configured scope. In MarkLogic 9 and later, the behavior changed for certain JSON property scope queries where the scope property value is an array of objects.

The behavior has changed for searches that have the following characteristics:

  • The query parameter of the property scope query is an and-query. Such a scope query effectively finds co-occurrences of matches to the and-query criteria within the specified scope.

  • In the document to be matched, the value of the scope property is an array of objects. The item type is determined by examining only the first item in the array.

Given this setup, in MarkLogic 9 and later, the query only matches if all the sub-queries of the and-query occur in the same array item. In MarkLogic 8, the query matches even when the and-query matches occur in different array items. All other forms of JSON property scope query are unchanged.

This change makes it possible to construct a JSON property scope query that constrains matches to occurrences with a single array item. In MarkLogic 8, this was not possible.

This change also affects the container-query element of a structured query and QBE container queries.

The following example query is of the form affected by this change. It finds co-occurrences of “prop1” with value “value1” and “prop2” with “value2” within the scope of “root”. (The and-query criteria can be arbitrarily complex.)

Language

Example Query

XQuery

cts:json-property-scope-query(
  "root", 
  cts:and-query((
    cts:json-property-value-query("prop1", "value1"),
    cts:json-property-value-query("prop2", "value2")
  ))
)

Server-Side JavaScript

cts.jsonPropertyScopeQuery(
  'root',
  cts.andQuery([
    cts.jsonPropertyValueQuery('prop1', 'value1'),
    cts.jsonPropertyValueQuery('prop2', 'value2')
  ])
);

If you search the following documents with the previous query shown, you get the results shown. The JSON properties that match the and-query criteria are shown in bold.

Sample Document

MarkLogic 8

MarkLogic 9

// (1) criteria met in different array items
{"root": [
  { "prop1": "value1", "prop2": "v" },
  { "prop1": "v", "prop2": "value2" }]}

Match

No match

// (2) criteria met in the same array item
{"root": [
  { "prop1": "value1", "prop2": "value2" },
  { "prop1": "v", "prop2": "v" }
]}

Match

Match

// (3) criteria met in a child property
{"root": {
  "child": [
    { "prop1": "value1", "prop2": "v" },
    { "prop1": "v", "prop2": "value2" }  ]
}}

Match

Match

Document (1) does not match in MarkLogic 9 and later because both and-query criteria are not satisfied in the same array item. Document (2) matches in MarkLogic 9 and later because both and-query criteria are satisfied in the same array item. The Document (3) results are unaffected because the value of the “root” property is not an array of objects.

You can restore the MarkLogic 8 behavior by using an and-query of multiple JSON property scope queries. For example, the following query matches Document (1) in MarkLogic 9 and later:

Language

Example Query

XQuery

cts:and-query((
  cts:json-property-scope-query(
    "root", cts:json-property-value-query("prop1", "value1")),
  cts:json-property-scope-query(
    "root", cts:json-property-value-query("prop2", "value2"))
))

Server-Side JavaScript

cts.andQuery([
  cts.jsonPropertyScopeQuery(
    'root', cts.jsonPropertyValueQuery('prop1', 'value1')),
  cts.jsonPropertyScopeQuery(
    'root', cts.jsonPropertyValueQuery('prop2', 'value2'))
]);

To ensure the modified queries match only when the and-query matches occur in the same instance of the scope property (“root” in the above examples), wrap it in JSON property scope query on the parent property. For example:

Language

Example Query

XQuery

cts:json-property-scope-query("parent-of-root",
  cts:and-query((
    cts:json-property-scope-query(
      "root", cts:json-property-value-query("prop1", "value1")),
    cts:json-property-scope-query(
      "root", cts:json-property-value-query("prop2", "value2"))
)))

Server-Side JavaScript

cts.jsonPropertyScopeQuery('parentOfRoot',
  cts.andQuery([
    cts.jsonPropertyScopeQuery(
      'root', cts.jsonPropertyValueQuery('prop1', 'value1')),
    cts.jsonPropertyScopeQuery(
      'root', cts.jsonPropertyValueQuery('prop2', 'value2'))
]));