marklogic/java-client-api

Expose op:sample-by function in Java Client API

llinggit opened this issue · 5 comments

As task in bugtrack, https://bugtrack.marklogic.com/55089
A sample query as below

xquery version "1.0-ml";
import module namespace op="http://marklogic.com/optic"
at "/MarkLogic/optic.xqy";
op:from-view("opticUnitTest", "musician")
=> op:sample-by(map:map()=>map:with("limit", 2))
=> op:result()

So we can address your issue, please include the following:

Version of MarkLogic Java Client API

See Readme.txt

Version of MarkLogic Server

See admin gui on port 8001 or run xdmp:version() in Query Console - port 8000)

Java version

Run java -version

OS and version

For MAC, run sw_vers.
For Windows, run systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
For Linux, run cat /etc/os-release and uname -r

Input: Some code to illustrate the problem, preferably in a state that can be independently reproduced on our end

Actual output: What did you observe? What errors did you see? Can you attach the logs? (Java logs, MarkLogic logs)

Expected output: What specifically did you expect to happen?

Alternatives: What else have you tried, actual/expected?

Besides writing a unit test using PlanBuilder.sampleByOptions(), please consider whether it makes sense to add

  • A PlanBuilderBase.AccessPlanBase.sampleBy() method overload that takes the limit as an int.
  • A PlanBuilderSubImpl.AccessPlanSubImpl,sampleBy() implementation that constructs the PlanSampleByOptionsImpl and calls the existing method

Thanks, Erik. Will do.

PlanSampleByOptions options = p.sampleByOptions().withLimit(2);

The unit test throws an error, "Server Message: OPTIC-INVALARGS: fn.error(null, 'OPTIC-INVALARGS', 'limit must be a positive number: '+length); -- Invalid arguments: limit must be a positive number: 4"

I found that it errors out at line 2731 of optic-impl.sjs. The number we passed in is treated as a string, not a number. Investigating.

The limit in PlanSampleByOptions is indeed a xs:int, but later changed to String in ExportablePlan.

Proposed changes:

Index: marklogic-client-api/src/main/java/com/marklogic/client/impl/PlanBuilderSubImpl.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/marklogic-client-api/src/main/java/com/marklogic/client/impl/PlanBuilderSubImpl.java b/marklogic-client-api/src/main/java/com/marklogic/client/impl/PlanBuilderSubImpl.java
--- a/marklogic-client-api/src/main/java/com/marklogic/client/impl/PlanBuilderSubImpl.java	(revision b495d4f5a70e8e953f6ba03a82ba74387729aef4)
+++ b/marklogic-client-api/src/main/java/com/marklogic/client/impl/PlanBuilderSubImpl.java	(date 1633408801496)
@@ -560,13 +560,13 @@
 
     return mapdef;
   }
-  static Map<String,String> makeMap(PlanSampleByOptions options) {
+  static Map<String,XsIntVal> makeMap(PlanSampleByOptions options) {
     if (options == null) {
       return null;
     }
 
     XsIntVal limit = options.getLimit();
-    return (limit == null) ? null : makeMap("limit", limit.toString());
+    return (limit == null) ? null : makeMap("limit", limit);
   }
   static Map<String,String> makeMap(PlanSparqlOptions options) {
     if (options == null) {
@@ -599,7 +599,15 @@
     return map;
   }
 
-  static BaseTypeImpl.BaseMapImpl asArg(Map<String,String> arg) {
+  static Map<String, XsIntVal> makeMap(String key, XsIntVal value) {
+    Map<String, XsIntVal> map = new HashMap<String, XsIntVal>();
+    if (key != null) {
+      map.put(key, value);
+    }
+    return map;
+  }
+
+  static BaseTypeImpl.BaseMapImpl asArg(Map<String, ?> arg) {
     if (arg == null) {
       return null;
     }