diff --git a/lib/plan-builder-base.js b/lib/plan-builder-base.js index 1e802640..cbeb9149 100644 --- a/lib/plan-builder-base.js +++ b/lib/plan-builder-base.js @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. */ 'use strict'; @@ -58,11 +58,8 @@ function castArg(arg, funcName, paramName, argPos, paramTypes) { } else if (arg instanceof Number || arg instanceof Boolean || arg instanceof String) { arg = arg.valueOf(); } else if (arg instanceof types.ServerType) { - // We added new VecVector ServerType which is not a sub-type of Item. This makes it a one-off type - // as paramTypes will not include VecVector in any other type checks. - // And if we get here the arg must be and only be a VecVector (arg._ns === 'vec') or we throw an Error if(arg._ns === 'vec'){ - return arg; + return arg._args; } throw new Error( `${argLabel(funcName, paramName, argPos)} must have type ${typeLabel(paramTypes)}` @@ -404,26 +401,6 @@ function castArg(arg, funcName, paramName, argPos, paramTypes) { }); } return true; - case 'PlanTransitiveClosureOptions': - const planTransitiveClosureOptionsSet = new Set(['minLength', 'min-length', 'maxLength', 'max-length']); - if(Object.getPrototypeOf(arg) === Map.prototype){ - arg.forEach((value, key) => { - if(!planTransitiveClosureOptionsSet.has(key)) { - throw new Error( - `${argLabel(funcName, paramName, argPos)} has invalid key- ${key}` - ); - } - }); - } else if (typeof arg === 'object') { - Object.keys(arg).forEach(key => { - if(!planTransitiveClosureOptionsSet.has(key)) { - throw new Error( - `${argLabel(funcName, paramName, argPos)} has invalid key- ${key}` - ); - } - }); - } - return true; default: return false; } diff --git a/lib/plan-builder-generated.js b/lib/plan-builder-generated.js index ebe596de..41b96764 100755 --- a/lib/plan-builder-generated.js +++ b/lib/plan-builder-generated.js @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. */ 'use strict'; @@ -14,7 +14,6 @@ version numbers for "since" annotations. const types = require('./server-types-generated.js'); const bldrbase = require('./plan-builder-base.js'); let patchArgs = []; -let columnBuilderArgs = []; class CtsExpr { constructor() { @@ -5459,23 +5458,6 @@ normalize(...args) { const paramdef = ['vector1', [types.VecVector, PlanColumn, PlanParam], false, false]; const checkedArgs = bldrbase.makeSingleArgs('vec.normalize', 1, paramdef, args); return new types.VecVector('vec', 'normalize', checkedArgs); - } -/** - * Returns a new vector which is a copy of the input vector with reduced precision. The precision reduction is achieved by clearing the bottom (32 - precision) bits of the mantissa for each dimension's float value. This can be useful for reducing storage requirements or for creating approximate vector representations. Provides a client interface to a server function. See {@link http://docs.marklogic.com/vec.precision|vec.precision} - * @method planBuilder.vec#precision - * @since 4.1.0 - * @param { VecVector } [vector] - The input vector to reduce precision. - * @param { XsUnsignedInt } [precision] - The number of mantissa bits to preserve (9-32 inclusive). Default is 16. Higher values preserve more precision. If the value is outside the valid range, throw VEC-INVALIDPRECISION. - * @returns { VecVector } - */ -precision(...args) { - const namer = bldrbase.getNamer(args, 'vector'); - const paramdefs = [['vector', [types.VecVector, PlanColumn, PlanParam], false, false], ['precision', [types.XsUnsignedInt, PlanColumn, PlanParam], false, false]]; - const checkedArgs = (namer !== null) ? - bldrbase.makeNamedArgs(namer, 'vec.precision', 1, new Set(['vector', 'precision']), paramdefs, args) : - bldrbase.makePositionalArgs('vec.precision', 1, false, paramdefs, args); - return new types.VecVector('vec', 'precision', checkedArgs); - } /** * Returns the difference of two vectors. The vectors must be of the same dimension. Provides a client interface to a server function. See {@link http://docs.marklogic.com/vec.subtract|vec.subtract} @@ -5511,33 +5493,16 @@ subvector(...args) { bldrbase.makePositionalArgs('vec.subvector', 2, false, paramdefs, args); return new types.VecVector('vec', 'subvector', checkedArgs); - } -/** - * Returns a new vector which is a copy of the input vector with each element truncated to a specific number of digits. Provides a client interface to a server function. See {@link http://docs.marklogic.com/vec.trunc|vec.trunc} - * @method planBuilder.vec#trunc - * @since 4.1.0 - * @param { VecVector } [vector] - The input vector to truncate. - * @param { XsInt } [n] - The numbers of decimal places to truncate to. The default is 0. Negative values cause that many digits to the left of the decimal point to be truncated. - * @returns { VecVector } - */ -trunc(...args) { - const namer = bldrbase.getNamer(args, 'vector'); - const paramdefs = [['vector', [types.VecVector, PlanColumn, PlanParam], false, false], ['n', [types.XsInt, PlanColumn, PlanParam], false, false]]; - const checkedArgs = (namer !== null) ? - bldrbase.makeNamedArgs(namer, 'vec.trunc', 1, new Set(['vector', 'n']), paramdefs, args) : - bldrbase.makePositionalArgs('vec.trunc', 1, false, paramdefs, args); - return new types.VecVector('vec', 'trunc', checkedArgs); - } /** * Returns a vector value. Provides a client interface to a server function. See {@link http://docs.marklogic.com/vec.vector|vec.vector} * @method planBuilder.vec#vector * @since 3.5.0 - * @param { XsAnyAtomicType } [values] - The value(s) to create the vector from. Can be a sequence or json:array of integer or floating-point numbers. Also accepts a string that has the format of a JSON array of Numbers, a string that was created by vec:base64-encode(), or a types.Node such as returned by xpath. + * @param { XsAnyAtomicType } [values] - The value(s) to create the vector from. Can be a sequence or json:array of integer or floating-point numbers. Also accepts a string that has the format of a JSON array of Numbers. Also accepts a string that was created by vec:base64-encode(). * @returns { VecVector } */ vector(...args) { - const paramdef = ['values', [types.XsAnyAtomicType, types.Node, PlanColumn, PlanParam], false, true]; + const paramdef = ['values', [types.XsAnyAtomicType, PlanColumn, PlanParam], false, true]; const checkedArgs = bldrbase.makeSingleArgs('vec.vector', 1, paramdef, args); return new types.VecVector('vec', 'vector', checkedArgs); } @@ -7086,13 +7051,6 @@ class PlanGroup extends types.ServerType { super(ns, fn, args); } -} -class PlanTransitiveClosureOptions extends types.ServerType { - - constructor(ns, fn, args) { - super(ns, fn, args); - } - } class PlanParamBinding extends types.ServerType { @@ -7136,167 +7094,12 @@ class PlanAnnTopKOptions extends types.ServerType { } } -/** - * ColumnBuilder object to construct a view for op.fromDocs. - * This class has been modified from the auto-generated classes to - * add chaining behavior to the methods to collect multiple method - * calls into a single ColumnBuilder object to send to /v1/rows. - * This is done by returning a new PlanColumnBuilderBase and follows - * the PatchBuilder pattern. - * @namespace planBuilder.ColumnBuilder - * @since 4.1.0 - */ -class PlanColumnBuilder extends types.ServerType { - - constructor(ns, fn, args) { - super(ns, fn, args); - } -/** - * Create a new column definition for use with op:from-docs. This method initializes the column with default properties unless overridden by additional chained methods. Default Behavior: If no other properties are set (such as xpath(), type(), or nullable()), the column defaults to: XPath: ./name (where name is the name passed to add-column()).Type: stringNullable: true Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.addColumn|op.addColumn} - * @method planBuilder.ColumnBuilder#addColumn - * @since 4.1.0 - * @param { PlanColumnName } [column] - The Column Builder Plan. You can either use the XQuery => chaining operator or specify the variable that captures the return value from the previous operation. - * @returns { planBuilder.ColumnBuilder } - */ -addColumn(...args) { - const paramdef = ['column', [PlanColumn, types.XsString], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.addColumn', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'add-column', checkedArgs)]); - } -/** - * Sets the collation for the column created by op:add-column. This only applies to columns with string types, as collations specify the order in which strings are sorted and how they are compared. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.collation|op.collation} - * @method planBuilder.ColumnBuilder#collation - * @since 4.1.0 - * @param { XsString } [collation] - the collation for string types - * @returns { planBuilder.ColumnBuilder } - */ -collation(...args) { - const paramdef = ['collation', [types.XsString], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.collation', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'collation', checkedArgs)]); - } -/** - * Sets the coordinate-system for the column created by op:add-column. This only applies to columns with geo types. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.coordinateSystem|op.coordinateSystem} - * @method planBuilder.ColumnBuilder#coordinateSystem - * @since 4.1.0 - * @param { XsString } [coordinateSystem] - the coordinate system for geo types - * @returns { planBuilder.ColumnBuilder } - */ -coordinateSystem(...args) { - const paramdef = ['coordinate-system', [types.XsString], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.coordinateSystem', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'coordinate-system', checkedArgs)]); - } -/** - * Sets the default value for the column created by op:add-column. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.default|op.default} - * @method planBuilder.ColumnBuilder#default - * @since 4.1.0 - * @param { Item } [defaultExpression] - the default value for the column - * @returns { planBuilder.ColumnBuilder } - */ -default(...args) { - const paramdef = ['default-expression', [types.Item, PlanColumn, PlanParam], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.default', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'default', checkedArgs)]); - } -/** - * Sets the vector dimension for the column created by op:add-column. It only applies when the column's type is set to "vector". If the vector to be extracted does not have the same dimension, the value will be rejected. There's no default dimension. Vectors of all dimensions are extracted. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.dimension|op.dimension} - * @method planBuilder.ColumnBuilder#dimension - * @since 4.1.0 - * @param { XsUnsignedInt } [dimension] - the vector dimension for the column - * @returns { planBuilder.ColumnBuilder } - */ -dimension(...args) { - const paramdef = ['dimension', [types.XsUnsignedInt], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.dimension', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'dimension', checkedArgs)]); - } -/** - * Sets the expression to create content or extract content from a document for the column created by op:add-column. It cannot be used together with op:xpath, as both of them define the content of the column. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.expr|op.expr} - * @method planBuilder.ColumnBuilder#expr - * @since 4.1.0 - * @param { Item } [expression] - the expression to create content or extract content from a document for the column - * @returns { planBuilder.ColumnBuilder } - */ -expr(...args) { - const paramdef = ['expression', [types.Item, PlanColumn, PlanParam], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.expr', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'expr', checkedArgs)]); - } -/** - * Set the column created by op:add-column nullable or not. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.nullable|op.nullable} - * @method planBuilder.ColumnBuilder#nullable - * @since 4.1.0 - * @param { XsBoolean } [bool] - whether the column is nullable - * @returns { planBuilder.ColumnBuilder } - */ -nullable(...args) { - const paramdef = ['bool', [types.XsBoolean], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.nullable', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'nullable', checkedArgs)]); - } -/** - * Set the data type of the column created by op:add-column. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.type|op.type} - * @method planBuilder.ColumnBuilder#type - * @since 4.1.0 - * @param { XsString } [type] - the data type of the column - * @returns { planBuilder.ColumnBuilder } - */ -type(...args) { - const paramdef = ['type', [types.XsString], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.type', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'type', checkedArgs)]); - } -/** - * Sets the units for the column created by op:add-column. This only applies to columns with geo types. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.units|op.units} - * @method planBuilder.ColumnBuilder#units - * @since 4.1.0 - * @param { XsString } [units] - the units for the column - * @returns { planBuilder.ColumnBuilder } - */ -units(...args) { - const paramdef = ['units', [types.XsString], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.units', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'units', checkedArgs)]); - } -/** - * This function extracts a sequence of child nodes from a column with node values -- especially, the document nodes from a document join. The path is an XPath (specified as a string) to apply to each node to generate a sequence of nodes as an expression value. Sets the XPath expression in the document from which to extract content for the column created by op:add-column. It cannot be used together with op:expr, as both of them define the content of the column. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.xpath|op.xpath} - * @method planBuilder.ColumnBuilder#xpath - * @since 4.1.0 - * @param { XsString } [path] - The name of the column from which to extract the child nodes. The column can be named with a string or a column function such as op:col, op:view-col, or op:schema-col, or constructed from an expression with the op:as function.It can also be op:context to refer to the node of the current processing row. - * @returns { planBuilder.ColumnBuilder } - */ -xpath(...args) { - const paramdef = ['path', [types.XsString], true, false]; - const checkedArgs = bldrbase.makeSingleArgs('PlanColumnBuilder.xpath', 1, paramdef, args); - return new PlanColumnBuilderBase([new PlanColumnBuilder('op', 'xpath', checkedArgs)]); - } -} - -/** - * Helper class to collect column builder operations. - * @namespace planBuilder.PlanColumnBuilderBase - * @since 4.1.0 - */ -class PlanColumnBuilderBase { - constructor(args) { - columnBuilderArgs.push(args); - return new PlanColumnBuilder('op', 'suboperators', columnBuilderArgs); - } -} class PlanJsonProperty extends types.ServerType { constructor(ns, fn, args) { super(ns, fn, args); } -} -class PlanContextExprCall extends types.ServerType { - - constructor(ns, fn, args) { - super(ns, fn, args); - } - } class PlanCtsReferenceMap extends types.ServerType { @@ -8281,24 +8084,6 @@ annTopK(...args) { return new PlanModifyPlan(this, 'op', 'ann-top-k', checkedArgs); } -/** - * This method performs a transitive closure operation over a graph-like structure, identifying all reachable node pairs from a given start node to an end node through one or more intermediate steps. A set of (start, end) node pairs where a path exists between them with a length between minLength and maxLength, inclusive. This models the SPARQL one-or-more (+) operator, enabling recursive or chained relationships to be queried efficiently. Provides a client interface to a server function. See {@link http://docs.marklogic.com/ModifyPlan.prototype.transitiveClosure|ModifyPlan.prototype.transitiveClosure} - * @method planBuilder.ModifyPlan#transitiveClosure - * @since 4.1.0 - * @param { PlanExprColName } [start] - The column is the starting node of the traversal. The column can be named with a string or a column function such as op:col, op:view-col, or op:schema-col, or constructed from an expression with the op:as function. - * @param { PlanExprColName } [end] - The column is the end node of the traversal. The column can be named with a string or a column function such as op:col, op:view-col, or op:schema-col, or constructed from an expression with the op:as function. - * @param { PlanTransitiveClosureOptions } [options] - This is either a sequence of strings or an object containing keys and values for the options to this operator. Options include: min-length This option is the minimum number of steps (edges) required in the path. It should be a non-negative integer, and the default is 1. max-length This option Maximum number of steps (edges) allowed in the path. It should be a non-negative integer, and the default is unlimited. - * @returns { planBuilder.ModifyPlan } - */ -transitiveClosure(...args) { - const namer = bldrbase.getNamer(args, 'start'); - const paramdefs = [['start', [PlanExprCol, PlanColumn, types.XsString], true, false], ['end', [PlanExprCol, PlanColumn, types.XsString], true, false], ['options', [PlanTransitiveClosureOptions], false, false]]; - const checkedArgs = (namer !== null) ? - bldrbase.makeNamedArgs(namer, 'PlanModifyPlan.transitiveClosure', 2, new Set(['start', 'end', 'options']), paramdefs, args) : - bldrbase.makePositionalArgs('PlanModifyPlan.transitiveClosure', 2, false, paramdefs, args); - return new PlanModifyPlan(this, 'op', 'transitive-closure', checkedArgs); - - } } /** * AccessPlan objects have methods and inherit {@link planBuilder.ModifyPlan} methods. @@ -8724,18 +8509,6 @@ patchBuilder(...args) { patchArgs = []; return new PlanPatchBuilderBase(new PlanPatchBuilder('op', 'patch-builder', checkedArgs)); } -/** - * Create column definitions which can be used in op:from-docs. Below functions are used to create column definitions. op:add-column, op:type, op:xpath, op:expr, op:nullable, op:default, op:dimension, op:coordinate-system, op:units, op:collation. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.columnBuilder|op.columnBuilder} - * @method planBuilder#columnBuilder - * @since 4.1.0 - - * @returns { planBuilder.ColumnBuilder } - */ -columnBuilder(...args) { - bldrbase.checkMaxArity('PlanBuilder.columnBuilder', args.length, 0); - columnBuilderArgs = []; - return new PlanColumnBuilderBase(new PlanColumnBuilder('op', 'column-builder', args)); - } /** * This function creates a placeholder for a literal value in an expression or as the offset or max for a limit. The op:result function throws in an error if the binding parameter does not specify a literal value for the parameter. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.param|op.param} * @method planBuilder#param @@ -9063,27 +8836,6 @@ fromDocUris(...args) { bldrbase.makePositionalArgs('PlanBuilder.fromDocUris', 1, false, paramdefs, args); return new PlanAccessPlan(null, 'op', 'from-doc-uris', checkedArgs); - } -/** - * This function dynamically maps semi-structured data (JSON/XML) into rows and columns without deploying a TDE template. It enables ad-hoc queries similar to Virtual Template Views but with additional flexibility, such as node output and advanced column customization. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.fromDocs|op.fromDocs} - * @method planBuilder#fromDocs - * @since 4.1.0 - * @param { PlanQueryDef } [ctsQuery] - Query to select documents for row generation . The query can be a cts:query or a string as a shortcut for a cts:word-query. - * @param { XsString } [contextPath] - XPath applied to each matched document; each result becomes a row. - * @param { PlanColumnBuilder } [columnSpec] - The column definitionss create by using op:column-builder - * @param { XsString } [qualifier] - Specifies a name for qualifying the column names in place of the combination of the schema and view names. Use cases for the qualifier include self joins. Using an empty string removes all qualification from the column names. - * @param { PlanSystemColumn } [systemCol] - An optional named fragment id column returned by op:fragment-id-col. One use case for fragment ids is in joins with lexicons or document content. - * @param { PlanNamespaceBindings } [namespaces] - Namespaces prefix (key) and uri (value). - * @returns { planBuilder.AccessPlan } - */ -fromDocs(...args) { - const namer = bldrbase.getNamer(args, 'cts-query'); - const paramdefs = [['cts-query', [types.CtsQuery, types.XsString], true, false], ['context-path', [types.XsString], true, false], ['column-spec', [PlanColumnBuilder], true, false], ['qualifier', [types.XsString], false, false], ['system-col', [PlanSystemColumn], false, false], ['namespaces', [PlanNamespaceBindings], false, false]]; - const checkedArgs = (namer !== null) ? - bldrbase.makeNamedArgs(namer, 'PlanBuilder.fromDocs', 3, new Set(['cts-query', 'context-path', 'column-spec', 'qualifier', 'system-col', 'namespaces']), paramdefs, args) : - bldrbase.makePositionalArgs('PlanBuilder.fromDocs', 3, false, paramdefs, args); - return new PlanAccessPlan(null, 'op', 'from-docs', checkedArgs); - } /** * This function returns a filter definition as input for a WHERE operation. As with a cts:query or sem:store, the filter definition cannot be used in an Optic Boolean expression but, instead, must be the only argument to the WHERE call. Add a separate WHERE call to filter based on an Optic Boolean expression. The condition must be a valid simple SQL Boolean expression expressed as a string. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.sqlCondition|op.sqlCondition} @@ -9477,33 +9229,22 @@ when(...args) { } /** - * This function extracts a sequence of child nodes from a column with node values -- especially, the document nodes from a document join. The path is an XPath (specified as a string) to apply to each node to generate a sequence of nodes as an expression value. Sets the XPath expression in the document from which to extract content for the column created by op:add-column. It cannot be used together with op:expr, as both of them define the content of the column. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.xpath|op.xpath} + * This function extracts a sequence of child nodes from a column with node values -- especially, the document nodes from a document join. The path is an XPath (specified as a string) to apply to each node to generate a sequence of nodes as an expression value. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.xpath|op.xpath} * @method planBuilder#xpath * @since 2.1.1 - * @param { PlanXpathExprColName } [column] - The name of the column from which to extract the child nodes. The column can be named with a string or a column function such as op:col, op:view-col, or op:schema-col, or constructed from an expression with the op:as function.It can also be op:context to refer to the node of the current processing row. + * @param { PlanColumnName } [column] - The name of the column from which to extract the child nodes. The column can be named with a string or a column function such as op:col, op:view-col, or op:schema-col, or constructed from an expression with the op:as function. * @param { XsString } [path] - An XPath (specified as a string) to apply to each node. * @param { PlanNamespaceBindings } [namespaceBindings] - A map of namespace bindings. The keys should be namespace prefixes and the values should be namespace URIs. These namespace bindings will be added to the in-scope namespace bindings in the evaluation of the path. * @returns { Node } */ xpath(...args) { const namer = bldrbase.getNamer(args, 'column'); - const paramdefs = [['column', [PlanExprCol, PlanColumn, types.XsString, PlanContextExprCall], true, false], ['path', [types.XsString, PlanColumn, PlanParam], true, false], ['namespace-bindings', [PlanNamespaceBindings], false, true]]; + const paramdefs = [['column', [PlanColumn, types.XsString], true, false], ['path', [types.XsString, PlanColumn, PlanParam], true, false], ['namespace-bindings', [PlanNamespaceBindings], false, true]]; const checkedArgs = (namer !== null) ? bldrbase.makeNamedArgs(namer, 'PlanBuilder.xpath', 2, new Set(['column', 'path', 'namespace-bindings']), paramdefs, args) : bldrbase.makePositionalArgs('PlanBuilder.xpath', 2, false, paramdefs, args); return new types.Node('op', 'xpath', checkedArgs); - } -/** - * This helper function returns the node from the current processing row. It is to be used in op:xpath, to reference the 'current item' instead of a doc column. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.context|op.context} - * @method planBuilder#context - * @since 4.1.0 - - * @returns { planBuilder.PlanContextExprCall } - */ -context(...args) { - bldrbase.checkMaxArity('PlanBuilder.context', args.length, 0); - return new PlanContextExprCall('op', 'context', args); } /** * This function constructs a JSON document with the root content, which must be exactly one JSON object or array node. Provides a client interface to a server function. See {@link http://docs.marklogic.com/op.jsonDocument|op.jsonDocument} diff --git a/test-app/src/main/ml-data/optic/transitive-closure/collections.properties b/test-app/src/main/ml-data/optic/transitive-closure/collections.properties deleted file mode 100644 index aff0a97c..00000000 --- a/test-app/src/main/ml-data/optic/transitive-closure/collections.properties +++ /dev/null @@ -1 +0,0 @@ -transClosureTripleSet.xml=http://test.optic.tc#,/graphs/inventory diff --git a/test-app/src/main/ml-data/optic/transitive-closure/permissions.properties b/test-app/src/main/ml-data/optic/transitive-closure/permissions.properties deleted file mode 100644 index f775de1e..00000000 --- a/test-app/src/main/ml-data/optic/transitive-closure/permissions.properties +++ /dev/null @@ -1 +0,0 @@ -*=rest-reader,read,rest-writer,update,app-user,read,app-builder,read,app-builder,update diff --git a/test-app/src/main/ml-data/optic/transitive-closure/transClosureTripleSet.xml b/test-app/src/main/ml-data/optic/transitive-closure/transClosureTripleSet.xml deleted file mode 100644 index c2130bdf..00000000 --- a/test-app/src/main/ml-data/optic/transitive-closure/transClosureTripleSet.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - -http://test.optic.tc#Alice -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#Bob - - -http://test.optic.tc#Bob -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#Carol - - -http://test.optic.tc#Carol -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#David - - -http://test.optic.tc#David -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#Eve - - -http://test.optic.tc#Eve -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#Frank - - -http://test.optic.tc#George -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#Helen - - -http://test.optic.tc#Helen -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#Ian - - -http://test.optic.tc#Alice -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#Cindy - - -http://test.optic.tc#Cindy -http://marklogic.com/transitiveClosure/parent -http://test.optic.tc#John - - -http://test.optic.tc#Alice -http://test.optic.tc#label -Alice - - -http://test.optic.tc#Bob -http://test.optic.tc#label -Bob - - -http://test.optic.tc#Eve -http://test.optic.tc#label -Eve - - -http://test.optic.tc#Cindy -http://test.optic.tc#label -Cindy - - -http://test.optic.tc#Helen -http://test.optic.tc#label -Helen - - -http://test.optic.tc#Ian -http://test.optic.tc#label -Ian - - -http://test.optic.tc#John -http://test.optic.tc#label -John - - -http://test.optic.tc#David -http://test.optic.tc#label -David - - -http://test.optic.tc#George -http://test.optic.tc#label -George - - -http://test.optic.tc#Carol -http://test.optic.tc#label -Carol - - -http://test.optic.tc#Frank -http://test.optic.tc#label -Frank - - - - diff --git a/test-basic/optic-fromDocs.js b/test-basic/optic-fromDocs.js deleted file mode 100644 index b8b78206..00000000 --- a/test-basic/optic-fromDocs.js +++ /dev/null @@ -1,343 +0,0 @@ -/* -* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. -*/ -'use strict'; - -const should = require('should'); - -const marklogic = require('../'); -const op = marklogic.planBuilder; - -const pbb = require('./plan-builder-base'); -var testconfig = require('../etc/test-config.js'); -const execPlan = pbb.execPlan; -const getResults = pbb.getResults; -var db = marklogic.createDatabaseClient(testconfig.restWriterConnection); -const Stream = require('stream'); -const testlib = require("../etc/test-lib"); -let result = new Set(); -let uris = []; -let serverConfiguration = {}; - -describe('optic-update fromDocs tests', function() { - - this.timeout(15000); - before(function (done) { - try { - testlib.findServerConfiguration(serverConfiguration); - setTimeout(()=>{done();}, 3000); - } catch(error){ - done(error); - } - }); - - describe('fromDocs', function () { - - before(function (done) { - // Insert test documents - const testDocs = [ - { - uri: '/test/fromDocs/artist-incomplete.json', - contentType: 'application/json', - content: { - artist: { - firstName: "Charlie", - lastName: "Parker", - // birthDate is missing - will test default value - instrument: "saxophone" - // genre is missing - will test default value - } - } - }, - { - uri: '/test/fromDocs/product-widget.json', - contentType: 'application/json', - content: { - product: { - name: "Widget", - price: 25.50, - quantity: 100 - } - } - }, - { - uri: '/test/fromDocs/location-seattle.json', - contentType: 'application/json', - collections: ['fromDocs'], - content: { - location: { - city: "Seattle", - point: "47.61, -122.33", - description: "Emerald City" - } - } - }, - { - // we already have a geospatial element index for 'point' in wgs84 - // in the test-app ml-gradle project. Use that. Use 'point' to indicate location. - uri: '/test/fromDocs/location-portland.json', - contentType: 'application/json', - collections: ['fromDocs'], - content: { - location: { - city: "Portland", - point: "45.52, -122.68", - description: "City of Roses" - } - } - }, - { - uri: '/test/fromDocs/location-san-francisco.json', - contentType: 'application/json', - collections: ['fromDocs'], - content: { - location: { - city: "San Francisco", - point: "37.77, -122.42", - description: "City by the Bay" - } - } - }, - { - uri: '/test/fromDocs/location-new-york.json', - contentType: 'application/json', - collections: ['fromDocs'], - content: { - location: { - city: "New York", - point: "40.71, -74.01", - description: "The Big Apple" - } - } - }, - { - // Bob and Alice are already loaded by ml-gradle test app - uri: '/test/fromDocs/person-donald.json', - contentType: 'application/json', - content: { - person: { - name: "Donald", - summary: "Bad Donald", - embedding: [ - -1.1, - -2.2, - -3.3 - ] - } - } - } - ]; - - let readable = new Stream.Readable({objectMode: true}); - testDocs.forEach(doc => { - readable.push(doc); - uris.push(doc.uri); - }); - readable.push(null); - - db.documents.writeAll(readable, { - onCompletion: () => done() - }); - }); - - after(function (done) { - if (uris.length > 0) { - db.documents.remove(uris) - .result(() => done()) - .catch(done); - } else { - done(); - } - }); - - it('fromDocs basic', function (done) { - const plan = op.fromDocs( - op.cts.wordQuery('Coltrane'), - '/musician', - op.columnBuilder() - .addColumn('lastName').xpath('./lastName').type('string') - .addColumn('firstName').xpath('./firstName').type('string') - .addColumn('dob').xpath('./dob').type('string') - .addColumn('instrument').xpath('./instrument').type('string'), - "MyView" - ); - execPlan(plan).then(function (response) { - const output = getResults(response); - output.length.should.equal(1); - output[0]['MyView.lastName'].value.should.equal('Coltrane'); - output[0]['MyView.firstName'].value.should.equal('John'); - output[0]['MyView.dob'].value.should.equal('1926-09-23'); - output[0]['MyView.instrument'].value.should.equal('saxophone'); - done(); - }).catch(done); - }); - - it('fromDocs with default', function (done) { - const plan = op.fromDocs( - op.cts.wordQuery('Parker'), - '/artist', - op.columnBuilder() - .addColumn('lastName').xpath('./lastName').type('string').collation('http://marklogic.com/collation/') - .addColumn('firstName').xpath('./firstName').type('string').collation('http://marklogic.com/collation/') - .addColumn('birthDate').xpath('./birthDate').type('string').default('Unknown') - .addColumn('instrument').xpath('./instrument').type('string') - .addColumn('genre').xpath('./genre').type('string').default('Jazz'), - "ArtistView" - ); - execPlan(plan).then(function (response) { - const output = getResults(response); - output.length.should.equal(1); - output[0]['ArtistView.lastName'].value.should.equal('Parker'); - output[0]['ArtistView.firstName'].value.should.equal('Charlie'); - output[0]['ArtistView.birthDate'].value.should.equal('Unknown'); - output[0]['ArtistView.instrument'].value.should.equal('saxophone'); - output[0]['ArtistView.genre'].value.should.equal('Jazz'); - done(); - }).catch(done); - }); - - it('fromDocs with expr', function (done) { - const plan = op.fromDocs( - op.cts.wordQuery('Widget'), - '/product', - op.columnBuilder() - .addColumn('name').xpath('./name').type('string') - .addColumn('price').xpath('./price').type('decimal') - .addColumn('quantity').xpath('./quantity').type('integer') - .addColumn('twoToTheThirdPower').nullable(true) - .expr(op.math.pow(2, 3)) - .type('integer'), - "ProductView" - ); - execPlan(plan).then(function (response) { - const output = getResults(response); - output.length.should.equal(1); - output[0]['ProductView.name'].value.should.equal('Widget'); - output[0]['ProductView.price'].value.should.equal(25.50); - output[0]['ProductView.quantity'].value.should.equal(100); - output[0]['ProductView.twoToTheThirdPower'].value.should.equal(8); - done(); - }).catch(done); - }); - - it('fromDocs with op.context() and op.xpath()', function (done) { - const plan = op.fromDocs( - op.cts.wordQuery('Widget'), - '/product', - op.columnBuilder() - .addColumn('name').xpath('./name').type('string') - .addColumn('quantity').xpath('./quantity').type('integer') - .addColumn('price').xpath('./price').type('decimal') - .addColumn('totalCost').nullable(true) - .expr(op.multiply( - op.xs.decimal(op.xpath(op.context(), './price')), - op.xs.integer(op.xpath(op.context(), './quantity')) - ) - ) - .type('decimal'), - "ProductView" - ); - execPlan(plan).then(function (response) { - const output = getResults(response); - output.length.should.equal(1); - output[0]['ProductView.name'].value.should.equal('Widget'); - output[0]['ProductView.price'].value.should.equal(25.50); - output[0]['ProductView.quantity'].value.should.equal(100); - output[0]['ProductView.totalCost'].value.should.equal(2550); - done(); - }).catch(done); - }); - - it('fromDocs with geospatial query', function (done) { - - const portlandPoint = op.cts.point(45.52, -122.68); - const searchRadius = 650; // miles - // geospatial element index is defined for 'point' in wgs84 - const plan = op.fromDocs( - op.cts.collectionQuery('fromDocs'), - '/location', - op.columnBuilder() - .addColumn('city').xpath('./city').type('string') - .addColumn('location-wgs84').xpath('./point').type('point').coordinateSystem('wgs84') - .addColumn('description').xpath('./description').type('string'), - "LocationView" - ) - .where( - op.cts.jsonPropertyGeospatialQuery - ( - 'point', - op.cts.circle(searchRadius, portlandPoint), - ['coordinate-system=wgs84'] - ) - ); - - execPlan(plan).then(function (response) { - const output = getResults(response); - output.length.should.be.equal(3); - const cities = output.map(row => row['LocationView.city'].value); - cities.should.containEql('Portland'); - cities.should.containEql('Seattle'); - cities.should.containEql('San Francisco'); - cities.should.not.containEql('New York'); - done(); - }).catch(done); - }); - - it('fromDocs with vector and dimension', function (done) { - - const testVector = op.vec.vector([1,2,3]); - const plan = op.fromDocs( - op.cts.wordQuery('*'), - '/person', - op.columnBuilder() - .addColumn('name').xpath('./name').type('string') - .addColumn('summary').xpath('./summary').type('string') - .addColumn('embedding').xpath('vec:vector(./embedding)').type('vector').dimension(3) - .addColumn('cosineDistance').nullable(true).expr( - op.vec.cosineDistance - ( - op.vec.vector(testVector), - op.vec.vector(op.xpath(op.context(), './embedding')) - ) - ).type('double') - .addColumn('euclideanDistance').nullable(true).expr( - op.math.trunc( - op.vec.euclideanDistance - ( - op.vec.vector(testVector), - op.vec.vector(op.xpath(op.context(), './embedding')) - ) - , 4) - ).type('double') - , - "PersonView" - ).where( - op.lt( - op.vec.cosineDistance - ( - op.vec.vector(testVector), - op.viewCol('PersonView', 'embedding') - ) - , - op.xs.double(0.5) - ) - ) - .orderBy(op.viewCol('PersonView', 'euclideanDistance')); - - execPlan(plan).then(function (response) { - const output = getResults(response); - output.length.should.be.equal(2); - const distances = output.map(row => row['PersonView.euclideanDistance'].value); - distances[0].should.be.approximately(0.3741, 0.0001); // Alice is .3741 from testVector - distances[1].should.be.approximately(12.1466, 0.0001); // Bob is 12.1466 from testVector - const names = output.map(row => row['PersonView.name'].value); - names.should.containEql('Alice'); - names.should.containEql('Bob'); - names.should.not.containEql('Donald'); - done(); - }).catch(done); - }); - - - }); -}); \ No newline at end of file diff --git a/test-basic/optic-vector.js b/test-basic/optic-vector.js index b552ba1a..bc29330d 100644 --- a/test-basic/optic-vector.js +++ b/test-basic/optic-vector.js @@ -1,12 +1,12 @@ /* -* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. */ 'use strict'; const should = require('should'); const marklogic = require('../'); -const op = marklogic.planBuilder; +const p = marklogic.planBuilder; const pbb = require('./plan-builder-base'); const execPlan = pbb.execPlan; @@ -34,189 +34,129 @@ describe('tests for new vector functions.', function() { }); it('vec.add', function(done) { - const vec1 = op.vec.vector([1]); - const vec2 = op.vec.vector([2]); - testPlan([""],op.vec.add(vec1, vec2)) + const vec1 = p.vec.vector([0.000000000001]); + const vec2 = p.vec.vector([0.000000000001, 0.000000000002]); + testPlan([""],p.vec.add(p.vec.subvector(vec1,0),p.vec.subvector(vec2,1))) .then(function(response) { - // add([1], [2]) = [3] (element-wise addition) - assert(response.rows[0].t.value[0] == 3, 'vec.add did not return expected value: [1] + [2] should be [3]'); + assert(response.rows[0].t.value[0][0] =='1e-12') + assert(response.rows[0].t.value[1][0]=='2e-12') done(); }).catch(error => done(error)); }); it('vec.subtract', function(done) { - const vec1 = op.vec.vector([2]); - const vec2 = op.vec.vector([1]); - testPlan([""],op.vec.subtract(vec1, vec2)) + const vec1 = p.vec.vector([0.000000000002]); + const vec2 = p.vec.vector([0.000000000001]); + testPlan([""],p.vec.subtract(p.vec.subvector(vec1,0),p.vec.subvector(vec2,0))) .then(function(response) { - // vec.subtract([2], [1]) = [1] (element-wise subtraction) - assert(response.rows[0].t.value[0] == 1, 'vec.subtract did not return expected value: [2] - [1] should be [1]'); + assert(response.rows[0].t.value[0][0] =='2e-12') + assert(response.rows[0].t.value[1][0]=='1e-12') done(); }).catch(error => done(error)); }); - it('vec.base64Decode', function(done) { - const vec1 = op.vec.vector([0.002]); - testPlan([""],op.vec.subvector(op.vec.base64Decode(op.vec.base64Encode(op.vec.subvector(vec1,0))),0)) + it('vec.base64decode', function(done) { + + const vec1 = p.vec.vector([0.002]); + testPlan([""],p.vec.subvector(p.vec.base64Decode(p.vec.base64Encode(p.vec.subvector(vec1,0))),0)) .then(function(response) { - // Round-trip encode/decode returns [0.002] - assert(response.rows[0].t.value[0] == 0.002, 'vec.base64Decode did not return expected value for vector [0.002] after round-trip encode/decode'); + assert(response.rows[0].t.value[0][0] =='0.002') done(); }).catch(error => done(error)); }); it('vec.base64Encode', function(done) { - testPlan([""],op.vec.base64Encode(op.vec.vector([0.002]))) + const vec1 = p.vec.vector([0.002]); + testPlan([""],p.vec.base64Encode(p.vec.subvector(vec1,0))) .then(function(response) { - // qconsole shows that encoding vector vec.base64Encode([0.002]) returns 'AAAAAAEAAABvEgM7' - assert(response.rows[0].t.value =='AAAAAAEAAABvEgM7', 'vec.base64Encode did not return expected value for vector [0.002] which should be "AAAAAAEAAABvEgM7"'); + assert(response.rows[0].t.value =='AAAAAAEAAABvEgM7') done(); }).catch(error => done(error)); }); it('vec.cosine', function(done) { - // orthogonal vectors should have cosine similarity of 0, round down to 0 to be sure (floats) - const vec1 = op.vec.vector([1, 1]) - const vec2 = op.vec.vector([-1, 1]) - - testPlan([""],op.math.floor(op.vec.cosine(vec1, vec2))) - .then(function(response) { - assert(response.rows[0].t.value == 0, 'Cosine similarity between orthogonal vectors should be 0'); - }).catch(error => done(error)); - - // cosine similarity between subvectors [1,2,3] and [5,6,7] should be approximately 0.968329 (to 6 decimal places) - testPlan([""],op.math.trunc(op.vec.cosine(op.vec.vector([1,2,3]),op.vec.vector([5,6,7])), 6)) - .then(function(response) { - assert(response.rows[0].t.value == '0.968329', 'Cosine (directional similarity) between vectors [1,2,3] and [5,6,7] should be approximately 0.968329'); - }).catch(error => done(error)); + const vec1 = p.vec.vector([1, 2, 3]) + const vec2 = p.vec.vector([4, 5, 6,7]) - // cosine similarity between subvectors [1,2,3] and [5,6,7] should be approximately 0.96832 - // and cosine distance should be approximately 0.03167 which is 1 - cosine similarity. - testPlan([""],op.vec.vector([ - op.math.trunc(op.vec.cosine(op.vec.vector([1,2,3]),op.vec.vector([5,6,7])), 5), - op.math.trunc(op.vec.cosineDistance(op.vec.vector([1,2,3]),op.vec.vector([5,6,7])), 5), - ])) + testPlan([""],p.vec.cosine(p.vec.subvector(vec1,0),p.vec.subvector(vec2,1))) .then(function(response) { - assert(response.rows[0].t.value[0] == '0.96832', 'Cosine (directional similarity) between subvectors [1,2,3] and [5,6,7] should be approximately 0.96833.'); - assert(response.rows[0].t.value[1] == '0.03167', 'Cosine distance between subvectors [1,2,3] and [5,6,7] should be approximately 0.03167, or 1 - cosine similarity.'); + assert(response.rows[0].t.value != null); done(); }).catch(error => done(error)); - - }); it('vec.dimension', function(done) { - testPlan([""],op.vec.dimension(op.vec.vector([1, 2, 3]))) + + testPlan([""],p.vec.dimension(p.vec.vector([1, 2, 3]))) .then(function(response) { - assert(response.rows[0].t.value == 3, 'Dimension of vector [1,2,3] should be 3'); + assert(response.rows[0].t.value == 3); done(); }).catch(error => done(error)); }); - it('vec.dotProduct', function(done) { - const vec1 = op.vec.vector([1, 2, 3]) - const vec2 = op.vec.vector([4, 5, 6, 7]) + it('vec.dotproduct', function(done) { + const vec1 = p.vec.vector([1, 2, 3]) + const vec2 = p.vec.vector([4, 5, 6,7]) - // Dot product between subvectors [1,2,3] and [5,6,7] is (1*5) + (2*6) + (3*7) = 5 + 12 + 21 = 38 - testPlan([""],op.vec.dotProduct( - op.vec.subvector(vec1,0), - op.vec.subvector(vec2,1,3)) - ) + testPlan([""],p.vec.cosine(p.vec.subvector(vec1,0),p.vec.subvector(vec2,1))) .then(function(response) { - assert(response.rows[0].t.value == 38, 'Dot product between subvectors [1,2,3] and [5,6,7] should be 38'); + assert(response.rows[0].t.value == '0.968329608440399'); done(); }).catch(error => done(error)); }); it('vec.euclideanDistance', function(done) { - const vec1 = op.vec.vector([1, 2, 3]) - const vec2 = op.vec.vector([4, 5, 6,7]) - - // Euclidean distance between subvectors [1,2] and [5,6] is - // sqrt((1-5)^2 + (2-6)^2) = sqrt(16 + 16) = sqrt(32) - // This is approx 5.65685 - testPlan([""], op.math.trunc( - op.vec.euclideanDistance( - op.vec.vector([1,2]), - op.vec.vector([5,6])) - , 5)) + const vec1 = p.vec.vector([1, 2, 3]) + const vec2 = p.vec.vector([4, 5, 6,7]) + + testPlan([""],p.vec.euclideanDistance(p.vec.subvector(vec1,0,2),p.vec.subvector(vec2,1,2))) .then(function(response) { - assert(response.rows[0].t.value == '5.65685', 'Euclidean distance between subvectors [1,2] and [5,6] should be approximately 5.65685, trunc() to 5 decimal places'); + assert(response.rows[0].t.value == '5.65685415267944'); done(); }).catch(error => done(error)); }); it('vec.get', function(done) { - testPlan([""],op.vec.get(op.vec.vector([1, 2, 3]),1)) + + testPlan([""],p.vec.get(p.vec.vector([1, 2, 3]),1)) .then(function(response) { - assert(response.rows[0].t.value == 2, 'Element at index 1 of vector [1,2,3] should be 2'); + assert(response.rows[0].t.value == 2); done(); }).catch(error => done(error)); }); it('vec.magnitude', function(done) { - testPlan([""],op.math.trunc(op.vec.magnitude(op.vec.vector([1, 2, 3])), 5)) + + testPlan([""],p.vec.magnitude(p.vec.vector([1, 2, 3]))) .then(function(response) { - // sqrt(1^2 + 2^2 + 3^2) = sqrt(14) ~= 3.74165 to 5 decimal places - assert(response.rows[0].t.value == '3.74165', 'Magnitude of [1,2,3] should be sqrt(1 + 4 + 9) ~= 3.74165 (trunc to 5 decimal places)'); + assert(response.rows[0].t.value == '3.74165749549866'); done(); }).catch(error => done(error)); }); it('vec.normalize', function(done) { - testPlan([""],(op.vec.normalize(op.vec.vector([1,2])))) + + testPlan([""],(p.vec.normalize(p.vec.subvector(p.vec.vector([1,2]),1)))) .then(function(response) { - // normalize([1,2]) = [1/sqrt(5), 2/sqrt(5)] - // value[0] = 1/sqrt(5) ~= 0.447214 - // value[1] = 2/sqrt(5) ~= 0.894427 - assert(response.rows[0].t.value[0] == 0.447214, 'Normalized first element of vector [1,2] should be approximately 0.447214'); - assert(response.rows[0].t.value[1] == 0.894427, 'Normalized second element of vector [1,2] should be approximately 0.894427'); + assert(response.rows[0].t.value == 2); done(); }).catch(error => done(error)); }); it('vec.vectorScore', function(done) { - testPlan([""],(op.vec.vectorScore(24684,0.1,0.1))) + const vec1 = p.vec.vector([1, 2, 3]) + testPlan([""],(p.vec.vectorScore(24684,0.1,0.1))) .then(function(response) { - assert(response.rows[0].t.value == 113124, 'vectorScore(24684,0.1,0.1) should be 113124'); + assert(response.rows[0].t.value == 113124); done(); }).catch(error => done(error)); }); it('vec.cosineDistance', function(done) { - // return a vector with two cosine distance calculations: one between identical direction vectors, - // one between opposite direction vectors - testPlan([""],(op.vec.vector([ - op.vec.cosineDistance(op.vec.vector([2, 2]), op.vec.vector([1, 1])), - op.vec.cosineDistance(op.vec.vector([2, 2]), op.vec.vector([-3, -3])) - ]))) - .then(function(response) { - assert(response.rows[0].t.value[0] == 0, 'Cosine distance should be 0 between identical direction vectors [2,2] and [1,1]'); - assert(response.rows[0].t.value[1] == 2, 'Cosine distance should be 2 between opposite direction vectors [2,2] and [-3,-3]'); - done(); - }).catch(error => done(error)); - }); - - it('vec.precision', function(done) { - // return a vector with the values of pi, e, and sqrt(2) by truncation; we expect to see [3, 2, 1] - testPlan([""],op.vec.precision(op.vec.vector([3.14159265, 2.71828182, 1.41421356]), 10)) - .then(function(response) { - assert(response.rows[0].t.value != null); - assert(response.rows[0].t.value[0] == 3); - assert(response.rows[0].t.value[1] == 2); - assert(response.rows[0].t.value[2] == 1); - done(); - }).catch(error => done(error)); - }); - - it('vec.trunc', function(done) { - // return a vector with the values of 1.123456789, 2.123456789, 3.123456789 truncated to 1 decimal place; - // we expect to see [1.1, 2.1, 3.1] - testPlan([""],(op.vec.trunc(op.vec.vector([1.123456789, 2.123456789, 3.123456789]), 1))) + testPlan([""],(p.vec.cosineDistance(p.vec.subvector(p.vec.vector([1, 2, 3]),0), + p.vec.subvector(p.vec.vector([4, 5, 6,7]),1)))) .then(function(response) { - assert(response.rows[0].t.value[0] == 1.1); - assert(response.rows[0].t.value[1] == 2.1); - assert(response.rows[0].t.value[2] == 3.1); + assert(response.rows[0].t.value == 0.0316703915596008); done(); }).catch(error => done(error)); }); diff --git a/test-basic/plan-builder-generated.js b/test-basic/plan-builder-generated.js index ca5dee68..678c24a0 100755 --- a/test-basic/plan-builder-generated.js +++ b/test-basic/plan-builder-generated.js @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. +* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. */ 'use strict'; @@ -1727,11 +1727,9 @@ describe('plan builder', function() { if(serverConfiguration.serverVersion < 12) { this.skip(); } - // AAAAAAMAAAAAAIA/AAAAQAAAQEA= is the ML base64 encoding string of the vector [1,2,3] - // Run vec.base64Encode(vec.vector([1,2,3])) in query console to generate - testPlan([p.xs.string("AAAAAAMAAAAAAIA/AAAAQAAAQEA=")],p.vec.base64Decode(p.col("1"))) + testPlan([p.xs.string("abc")], p.vec.base64Decode(p.col("1"))) .then(function(response) { - should(String(getResult(response).value)).equal('1,2,3'); + should(String(getResult(response).value).replace(/^ /, '')).equal('abc'); done(); }).catch(done); }); diff --git a/test-basic/service-caller.js b/test-basic/service-caller.js index 056e5299..aee8c50e 100644 --- a/test-basic/service-caller.js +++ b/test-basic/service-caller.js @@ -70,8 +70,7 @@ describe('Service caller', function() { }); }); - // errors all the time now, should fix. - it.skip('postOfUrlencodedForDocumentArray1 endpoint', function(done) { + it('postOfUrlencodedForDocumentArray1 endpoint', function(done) { const serviceDeclaration = JSON.parse(fs.readFileSync('test-basic-proxy/ml-modules/generated/postOfUrlencodedForDocument/service.json', {encoding: 'utf8'})); serviceDeclaration.endpointExtension = '.mjs'; diff --git a/test-basic/ssl-min-allow-tls-test.js b/test-basic/ssl-min-allow-tls-test.js index b69d7b1b..fb069030 100644 --- a/test-basic/ssl-min-allow-tls-test.js +++ b/test-basic/ssl-min-allow-tls-test.js @@ -12,7 +12,7 @@ let serverConfiguration = {}; let host = testconfig.testHost; describe('document write and read using min tls', function () { - this.timeout(12000); + this.timeout(10000); before(function (done) { testlib.findServerConfiguration(serverConfiguration); setTimeout(() => { diff --git a/test-basic/transitive-closure.js b/test-basic/transitive-closure.js deleted file mode 100644 index 8b6f815b..00000000 --- a/test-basic/transitive-closure.js +++ /dev/null @@ -1,141 +0,0 @@ -/* -* Copyright (c) 2015-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved. -*/ -'use strict'; - -const should = require('should'); - -const marklogic = require('../'); -const p = marklogic.planBuilder; - -const pbb = require('./plan-builder-base'); -const assert = require('assert'); -const testlib = require('../etc/test-lib'); -const { restWriterConnection } = require('../etc/test-config'); -let serverConfiguration = {}; -const tcGraph = p.graphCol('http://test.optic.tc#'); -const tcLabel = p.sem.iri('http://test.optic.tc#label'); -const person = p.col('person'); -const parent = p.col('parent'); -const ancestor = p.col('ancestor'); -const parentProp = p.sem.iri('http://marklogic.com/transitiveClosure/parent'); -const execPlan = pbb.execPlan; - -describe('tests for server-side transitive-closure method.', function () { - before(function (done) { - this.timeout(6000); - try { - testlib.findServerConfiguration(serverConfiguration); - setTimeout(() => { - if (serverConfiguration.serverVersion < 12) { - this.skip(); - } - done(); - }, 3000); - } catch (error) { - done(error); - } - }); - - it('with simple pattern full transitive closure', function (done) { - execPlan( - p.fromTriples([ - p.pattern(person, parentProp, ancestor, tcGraph) - ] - ).transitiveClosure(person, ancestor) - .orderBy([ancestor, person]) - ) - .then(function (response) { - const rows = response.rows; - rows.length.should.equal(21); - rows[0].should.have.property('person'); - rows[0].should.have.property('ancestor'); - done(); - }) - .catch(done); - }); - - it('with simple pattern minLength=2, transitive closure grandparents and up', function (done) { - execPlan( - p.fromTriples([ - p.pattern(person, parentProp, ancestor, tcGraph) - ] - ).transitiveClosure(person, ancestor, {'min-length': 2}) - ) - .then(function (response) { - const rows = response.rows; - // 2 steps or more excludes direct parent-child relationships - rows.length.should.equal(12); - rows[0].should.have.property('person'); - rows[0].should.have.property('ancestor'); - done(); - }) - .catch(done); - }); - - it('with simple pattern minLength=2, maxLength=2, transitive closure grandparents only', function (done) { - execPlan( - p.fromTriples([ - p.pattern(person, parentProp, ancestor, tcGraph) - ] - ).transitiveClosure(person, ancestor, {minLength: 2, maxLength: 2}) - ) - .then(function (response) { - const rows = response.rows; - // 2 steps only is grandparent relationships only - rows.length.should.equal(6); - rows[0].should.have.property('person'); - rows[0].should.have.property('ancestor'); - done(); - }) - .catch(done); - }); - - it('with simple pattern transitive closure with parent column as ancestor', function (done) { - execPlan( - p.fromTriples([ - p.pattern(person, parentProp, parent, tcGraph) - ] - ).transitiveClosure(person, p.as("ancestor", parent)) - ) - .then(function (response) { - const rows = response.rows; - rows.length.should.equal(21); - rows[0].should.have.property('person'); - rows[0].should.have.property('ancestor'); - done(); - }) - .catch(done); - }); - - it('with simple pattern transitive closure join to get labels', function (done) { - this.timeout(5000); - execPlan( - p.fromTriples([ - p.pattern(person, parentProp, ancestor, tcGraph) - ]) - .transitiveClosure(person, ancestor) - .joinLeftOuter( - p.fromTriples([ - p.pattern(person, tcLabel, p.col('person_name')) - ]) - ) - .joinLeftOuter( - p.fromTriples([ - p.pattern(ancestor, tcLabel, p.col('ancestor_name')) - ]) - ) - ) - .then(function (response) { - const rows = response.rows; - rows.length.should.equal(21); - rows[0].should.have.property('person'); - rows[0].should.have.property('ancestor'); - rows[0].should.have.property('person_name'); - rows[0].should.have.property('ancestor_name'); - done(); - }) - .catch(done); - }); - -});