Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,24 @@ public interface PlanBuilderBase {
*/
PlanBuilder.AccessPlan fromSearchDocs(CtsQueryExpr query, String qualifierName);
/**
* Provides a convenience for matching documents and constructing rows with the score,
* document URI, and document content. The convenience is equivalent to chaining
* Matches documents and constructs rows with the score, document URI, and document content,
* with control over which fragment types are searched via {@link PlanSearchOptions#withFragment(PlanSearchOptions.Fragment)}.
* <p>When no {@code fragment} option is set, behavior is equivalent to chaining
* {@link PlanBuilder#fromSearch(CtsQueryExpr)},
* {@link PlanBuilder.ModifyPlan#joinDocUri(String, String)},
* and {@link PlanBuilder.ModifyPlan#joinDoc(String, String)}.
* <p>The documents can be ordered by the score and limited for the most relevant
* documents.</p>
* When a non-default fragment type such as {@link PlanSearchOptions.Fragment#LOCKS} or
* {@link PlanSearchOptions.Fragment#PROPERTIES} is specified, the search targets those fragment
* types and the returned {@code uri} column resolves to the URI of the associated document.</p>
* <p>The documents can be ordered by the score and limited for the most relevant documents.</p>
* @param query The cts.query expression for matching the documents.
* @param qualifierName Specifies a name for qualifying the column names similar to a view name.
* @return a ModifyPlan object
* @since 7.0.0; requires MarkLogic 12 or higher.
* @param options Specifies scoring options and the fragment type to search. Use
* {@link PlanBuilder#searchOptions()} with
* {@link PlanSearchOptions#withFragment(PlanSearchOptions.Fragment)} to control
* the fragment scope.
* @return an AccessPlan object
* @since 8.2.0; requires MarkLogic 12.1 or higher.
Comment on lines +58 to +63
*/
PlanBuilder.AccessPlan fromSearchDocs(CtsQueryExpr query, String qualifierName, PlanSearchOptions options);
/**
Expand Down Expand Up @@ -131,7 +138,9 @@ public interface PlanBuilderBase {
* @param query The cts.query expression for matching the documents.
* @param columns The columns to project for the documents. See {@link PlanBuilder#colSeq(String...)}
* @param qualifierName Specifies a name for qualifying the column names similar to a view name.
* @param options Specifies how to calculate the score for the matching documents. See {@link PlanBuilder#searchOptions()}
* @param options Specifies how to calculate the score for the matching documents and which fragment
* types to return. Use {@link PlanBuilder#searchOptions()} with
* {@link PlanSearchOptions#withFragment(PlanSearchOptions.Fragment)} to control the fragment scope.
* @return an AccessPlan object
*/
PlanBuilder.AccessPlan fromSearch(CtsQueryExpr query, PlanExprColSeq columns, XsStringVal qualifierName, PlanSearchOptions options);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
* Copyright (c) 2010-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/
package com.marklogic.client.impl;

Expand Down Expand Up @@ -51,17 +51,20 @@ static class PlanSearchOptionsImpl implements PlanSearchOptions {
private PlanBuilderBaseImpl pb;
private XsFloatVal qualityWeight;
private ScoreMethod scoreMethod;
private XsDoubleVal bm25LengthWeight;
private XsDoubleVal bm25LengthWeight;
private Fragment fragment;
PlanSearchOptionsImpl(PlanBuilderBaseImpl pb) {
this.pb = pb;
}
PlanSearchOptionsImpl(PlanBuilderBaseImpl pb, XsFloatVal qualityWeight,
ScoreMethod scoreMethod, XsDoubleVal bm25LengthWeight) {
this(pb);
this.qualityWeight = qualityWeight;
this.scoreMethod = scoreMethod;
this.bm25LengthWeight = bm25LengthWeight;
}
PlanSearchOptionsImpl(PlanBuilderBaseImpl pb, XsFloatVal qualityWeight,
ScoreMethod scoreMethod, XsDoubleVal bm25LengthWeight,
Fragment fragment) {
this(pb);
this.qualityWeight = qualityWeight;
this.scoreMethod = scoreMethod;
this.bm25LengthWeight = bm25LengthWeight;
this.fragment = fragment;
}

@Override
public XsFloatVal getQualityWeight() {
Expand All @@ -71,43 +74,55 @@ public XsFloatVal getQualityWeight() {
public ScoreMethod getScoreMethod() {
return scoreMethod;
}
@Override
public XsDoubleVal getBm25LengthWeight() {
return bm25LengthWeight;
}
@Override
public XsDoubleVal getBm25LengthWeight() {
return bm25LengthWeight;
}
@Override
public Fragment getFragment() {
return fragment;
}
@Override
public PlanSearchOptions withQualityWeight(float qualityWeight) {
return withQualityWeight(pb.xs.floatVal(qualityWeight));
}
@Override
public PlanSearchOptions withQualityWeight(XsFloatVal qualityWeight) {
return new PlanSearchOptionsImpl(pb, qualityWeight, getScoreMethod(), getBm25LengthWeight());
return new PlanSearchOptionsImpl(pb, qualityWeight, getScoreMethod(), getBm25LengthWeight(), getFragment());
}
@Override
public PlanSearchOptions withScoreMethod(ScoreMethod scoreMethod) {
return new PlanSearchOptionsImpl(pb, getQualityWeight(), scoreMethod, getBm25LengthWeight());
}

@Override
public PlanSearchOptions withBm25LengthWeight(double bm25LengthWeight) {
return new PlanSearchOptionsImpl(pb, getQualityWeight(), getScoreMethod(), pb.xs.doubleVal(bm25LengthWeight));
}

Map<String,Object> makeMap() {
if (qualityWeight == null && scoreMethod == null && bm25LengthWeight == null) return null;

Map<String, Object> map = new HashMap<>();
if (qualityWeight != null) {
map.put("qualityWeight", qualityWeight);
}
if (scoreMethod != null) {
map.put("scoreMethod", scoreMethod.name().toLowerCase());
}
if (bm25LengthWeight != null) {
map.put("bm25LengthWeight", bm25LengthWeight);
}
return map;
}
return new PlanSearchOptionsImpl(pb, getQualityWeight(), scoreMethod, getBm25LengthWeight(), getFragment());
}

@Override
public PlanSearchOptions withBm25LengthWeight(double bm25LengthWeight) {
return new PlanSearchOptionsImpl(pb, getQualityWeight(), getScoreMethod(), pb.xs.doubleVal(bm25LengthWeight), getFragment());
}

@Override
public PlanSearchOptions withFragment(Fragment fragment) {
return new PlanSearchOptionsImpl(pb, getQualityWeight(), getScoreMethod(), getBm25LengthWeight(), fragment);
}

Map<String,Object> makeMap() {
if (qualityWeight == null && scoreMethod == null && bm25LengthWeight == null && fragment == null) return null;

Map<String, Object> map = new HashMap<>();
if (qualityWeight != null) {
map.put("qualityWeight", qualityWeight);
}
if (scoreMethod != null) {
map.put("scoreMethod", scoreMethod.name().toLowerCase());
}
if (bm25LengthWeight != null) {
map.put("bm25LengthWeight", bm25LengthWeight);
}
if (fragment != null) {
map.put("fragment", fragment.name().toLowerCase());
}
return map;
}
}

static class PlanParamBase extends BaseTypeImpl.BaseCallImpl<XsValueImpl.StringValImpl> implements PlanParamExpr {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public PlanBuilder.AccessPlan fromSearchDocs(CtsQueryExpr query) {
}
@Override
public PlanBuilder.AccessPlan fromSearchDocs(CtsQueryExpr query, String qualifierName) {
return fromSearchDocs(query, null, null);
return fromSearchDocs(query, qualifierName, null);
}
@Override
public PlanBuilder.AccessPlan fromSearchDocs(CtsQueryExpr query, String qualifierName, PlanSearchOptions options) {
Expand Down Expand Up @@ -694,7 +694,7 @@ public PlanPrefixer prefixer(String base) {
public PlanParamExpr param(String name) {
return new PlanParamBase(name);
}

@Override
public PlanParamExpr param(XsStringVal name) {
if (name == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
/*
* Copyright (c) 2010-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
* Copyright (c) 2010-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/
package com.marklogic.client.type;

/**
* An option controlling the scoring and weighting of fromSearch()
* for a row pipeline.
* Options controlling the scoring, weighting, and fragment scope for {@code fromSearch()} and
* {@code fromSearchDocs()} in a row pipeline. Use {@link #withFragment(Fragment)} to select which
* fragment types (document, properties, locks, or any) are searched and returned.
*
* <p>Fragment scope support was added in release 8.2.0 and requires MarkLogic 12.1 or higher.
* Scoring and weighting options apply to all supported MarkLogic versions.</p>
*/
public interface PlanSearchOptions {

Expand Down Expand Up @@ -38,6 +42,34 @@ public interface PlanSearchOptions {
*/
PlanSearchOptions withBm25LengthWeight(double bm25LengthWeight);

/**
* @since 8.2.0; requires MarkLogic 12.1 or higher.
*/
Fragment getFragment();

/**
* Specifies the type of fragment to search and return. Defaults to {@link Fragment#DOCUMENT} when no option
* is specified. Applies to both {@code fromSearch()} and {@code fromSearchDocs()}.
*
* @param fragment the fragment scope to select
* @return a new PlanSearchOptions with the fragment set
* @since 8.2.0; requires MarkLogic 12.1 or higher.
*/
PlanSearchOptions withFragment(Fragment fragment);
Comment on lines +48 to +58

/**
* Controls which type of fragments are searched and returned by {@code fromSearch()} and
* {@code fromSearchDocs()}.
*
* @since 8.2.0; requires MarkLogic 12.1 or higher.
*/
enum Fragment {
DOCUMENT,
ANY,
PROPERTIES,
LOCKS
}

enum ScoreMethod {
LOGTFIDF,
LOGTF,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2010-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
*/
package com.marklogic.client.test.junit5;

import com.marklogic.client.test.Common;
import com.marklogic.client.test.MarkLogicVersion;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;

public class RequiresML12Dot1 implements ExecutionCondition {

private static MarkLogicVersion markLogicVersion;

@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
if (markLogicVersion == null) {
markLogicVersion = Common.getMarkLogicVersion();
}
boolean supported =
(markLogicVersion.getMajor() == 12 && markLogicVersion.getMinor() != null && markLogicVersion.getMinor() >= 1) ||
markLogicVersion.getMajor() > 12;
return supported ?
ConditionEvaluationResult.enabled("MarkLogic is version 12.1 or higher") :
ConditionEvaluationResult.disabled("MarkLogic is version 12.0.x or lower");
}
}
Loading
Loading