Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Document XPath searching with Marklogic's Java search API vs XQuery/XSLT API

I have the following Marklogic query that, when run in the query console, allows me to retrieve my system user's who have admin privileges:

xquery version "1.0-ml";
import schema namespace bfa="http://bitfood.org/auth" at "schema/auth/bitfood-auth.xsd";
cts:search(/bfa:AppUser[bfa:appAccess/@appRole = "ROLE_SYS_ADMIN"], cts:and-query(()))

Pardon my ignorance, but is it possible to implement this query using the Java client API only?

I know I could use the raw query via XCC but I'm trying to avoid that as much as possible.

I've been digging through the Java client API's documentation which, unfortunately, deals briefly with other search methods and have found nothing hinting that this is possible.

UPDATE 1: Guys, I think I've hit a showstopper here.

According to this question, the Query Options building facilities of the Java client API are marked as deprecated.

@ehennum suggests an alternative which uses either XML or JSON query options. However, such query option specifications are still essentially defined as raw Strings in the code:

String xmlOptions =
  "<search:options "+
        "xmlns:search='http://marklogic.com/appservices/search'>"+
      "<search:constraint name='industry'>"+
        "<search:value>"+
          "<search:element name='industry' ns=''/>"+
        "</search:value>"+
      "</search:constraint>"+
  "</search:options>";

Granted, I could use JAXB, JDOM, files or some other tool to create the XML, but my personal opinion is that we are still resorting to storing queries in resource files in the code, which is not a bad thing in itself, but without careful consideration could lead to code maintenance nightmares.

Furthermore, the fact that these options need to be persisted via REST at the server introduces one more layer of potential problems in case this is mandatory since the options might need to be synchronized with every database instance that is meant to work with a code base.

So, if the Marklogic devs are listening, I think the Java client API isn't as mature or documented as I expected it to be.

I have two options so far:

1) I could hardcode my XCC queries in String files and try to use parameter placeholders to insert the data that I need and retrieve via an XCC session. Or.

2) See if there are any XSD files for the http://marklogic.com/appservices/search namespace and create static JAXB objects from them in order to build some sort of "criteria" classes a la Hibernate or QueryDSL which, sadly I must say, already supports some level of MongoDB querying.

Guys, really, bring some sort of fluent querying facilities like QueryDSL to Marklogic and get rid of this Rube Goldberg querying machine.

Update 2: Seems as if this might be addressed in ML7. Looking forward to it.

Thanks!

like image 265
Jesús Zazueta Avatar asked Oct 04 '22 02:10

Jesús Zazueta


1 Answers

Background: the Java API is a layer on the REST API is a layer on the Search API is a layer on cts:search

You can express this query in the Search API.

  • Use a searchable expression for the first parameter in your query options http://docs.marklogic.com/guide/search-dev/search-api#id_43671

  • Use an empty and query for the structured query http://docs.marklogic.com/guide/search-dev/structured-query#id_83674

Using the Java API, you can search using the query options and structured query as a RawCombinedQueryDefinition.

All that said, you could just also search for an element-query on bfa:AppUser containing a value constraint query on bfa:appAccess/@appRole of "ROLE_SYS_ADMIN"

While XPath can be convenient, it's a good idea to become conversant in query expressions to understand the full power and flexibility of the database.

Update 1:

A few things to consider:

  • A query in the Search API has two parts: the query (expressed either with Google-style string search or with JSON or XML structured search) and the query options. The StructuredQueryBuilder builds structured search. The QueryOptionsBuilder only built the query options.

  • In ML 6.0-3, the REST API introduced support for combined search, which provides both parts in a single request. The Java API added support for such requests through the RawCombinedQueryDefinition class.

  • ML7 is expanding structured search to reduce or eliminate the need for query options with structured search. StructuredQueryBuilder is enhanced in ML7 to support the new features of structured search. In ML7, you'll be able to write your example query above entirely in StructuredQueryBuilder without any need for query options.

  • When we compared the code constructing query options with QueryOptionsBuilder and with JDOM or XOM, it was hard to see much LOC benefit in the builder.

  • You don't have to hardcode query options in a string. For separation of concerns, you can read JSON or XML query options from a file or from many other sources. (Please see the implementations of the http://docs.marklogic.com/javadoc/client/com/marklogic/client/io/marker/QueryOptionsReadHandle.html marker interface.)

  • Query options provide a declaration instead of executable code. The parallel would be with Spring configuration files rather than with SPL files.

BTW, while JAXB is great for designs sourced in Java classes, JAXB can be quite painful for designs sourced in a complex XML schema. The search schema takes advantage of the powerful capabilities of XML schemas. When we explored this route, we concluded that JAXB was not not going to help provide an interface to query options.

like image 181
ehennum Avatar answered Oct 12 '22 12:10

ehennum