2

I am trying to get an aggregate query to run using the ML Java API, and am having a bit of trouble. I have followed the documentation, but there is a requirement for a values constraint, and i'm not really sure what that is supposed to look like. I tried the following:

    String options =
            "<options xmlns:search=\"http://marklogic.com/appservices/search\">" +
            "   <values name=\"average\">" +
            "       <range type=\"xs:string\">" +
            "           <element ns=\"\" name=\"content-id\"/>" +
            "       </range>" +
            "   </values>" +
            "</options>";

    StringHandle handle = new StringHandle(options);
    QueryOptionsManager optMgr = client.newServerConfigManager().newQueryOptionsManager();
    optMgr.writeOptions("average", handle);
    QueryManager queryManager = client.newQueryManager();
    StructuredQueryBuilder queryBuilder = queryManager.newStructuredQueryBuilder();
    ValuesDefinition valuesDefinition = queryManager.newValuesDefinition("average");
    valuesDefinition.setAggregate("avg");
    valuesDefinition.setQueryDefinition(queryBuilder.value(queryBuilder.element("content-id"),contentId));

    ValuesHandle results = queryManager.values(valuesDefinition, new ValuesHandle());

I took a stab at the options based on some other options i'm using. However, when I try to write the options it tells me Invalid Content: Unexpected Payload.

I get the feeling i'm going about this the wrong way. Essentially I want to find all documents that have a given value in the element "content-id", and then get the average of another element called "star-rating".

Should the options be set for "content-id" or "star-rating"? The documentation doesn't show the use of a queryDefinition, should I remove that? Modify it? Is there an easier way to do this in Java?

Edit: Forgot to mention, I also created an element range index on content-id with type string.

4
  • 1
    You're right to add setQueryDefinition to filter on "content-id". However, you don't need to use options to filter by a given value in "content-id". Just use queryBuilder.range() rather than queryBuilder.value(). You do need "star-rating" in your options under <values> and your valuesDefinition should center around that. Commented Apr 10, 2017 at 22:22
  • @SamMefford I changed to range() and modified the options and put star-rating in instead of content-id, but I am getting an error saying Invalid parameter: No values or tuples specification named: star-rating Commented Apr 11, 2017 at 14:39
  • Tried Googling the error but i'm not getting anything Commented Apr 11, 2017 at 14:55
  • @SamMefford never-mind my above comment. It was a dumb mistake of forgetting to add the options name to the query builder. It appears to be working now. Thanks! Commented Apr 11, 2017 at 16:33

1 Answer 1

2

With the guidance of @SamMefford I was able to reach a solution. It looks like this:

    String options =
            "<options xmlns=\"http://marklogic.com/appservices/search\">" +
            "   <values name=\"star-rating\">" +
            "       <range type=\"xs:float\">" +
            "           <element ns=\"\" name=\"star-rating\"/>" +
            "       </range>" +
            "   </values>" +
            "</options>";

    StringHandle handle = new StringHandle(options);
    QueryOptionsManager optMgr = client.newServerConfigManager().newQueryOptionsManager();
    optMgr.writeOptions("star-rating", handle);
    QueryManager queryManager = client.newQueryManager();
    StructuredQueryBuilder queryBuilder = 
        queryManager.newStructuredQueryBuilder("star-rating");
    ValuesDefinition valuesDefinition = queryManager.newValuesDefinition("star-rating");
    valuesDefinition.setAggregate("avg");
    valuesDefinition.setQueryDefinition(
        queryBuilder.range(
            queryBuilder.element("content-id"),"string", 
            StructuredQueryBuilder.Operator.EQ,contentId
        )
    );

    String results = queryManager.values(valuesDefinition, new ValuesHandle())
       .getAggregate("avg").getValue();

The options were created around the field that I wanted the average of. I created element indexes for both < star-rating > and < content-id >. The query then allowed me to filter to records with a specific content-id, and then get the average value of their star-ratings.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.