From c672b2bafecaf8c6114cce0ef801d5aaccbbfda3 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:18:10 +0200 Subject: [PATCH 01/46] Data API adapter: numeric filter operators accept integer values less than 2^32 --- .../dataapi/opdispensers/DataApiOpDispenser.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 1f6f32223..8bed2fcb6 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -100,17 +100,17 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser - filtersList.add(Filters.gt(fieldName, (long) fieldValue)); + filtersList.add(Filters.gt(fieldName, ((Number) fieldValue).longValue())); case "gte" -> - filtersList.add(Filters.gte(fieldName, (long) fieldValue)); + filtersList.add(Filters.gte(fieldName, ((Number) fieldValue).longValue())); case "hasSize" -> - filtersList.add(Filters.hasSize(fieldName, (int) fieldValue)); + filtersList.add(Filters.hasSize(fieldName, ((Number) fieldValue).intValue())); case "in" -> filtersList.add(Filters.in(fieldName, fieldValue)); case "lt" -> - filtersList.add(Filters.lt(fieldName, (long) fieldValue)); + filtersList.add(Filters.lt(fieldName, ((Number) fieldValue).longValue())); case "lte" -> - filtersList.add(Filters.lte(fieldName, (long) fieldValue)); + filtersList.add(Filters.lte(fieldName, ((Number) fieldValue).longValue())); case "ne" -> filtersList.add(Filters.ne(fieldName, fieldValue)); case "nin" -> From dbfb1db00f298a4676f0b3c9a52a6642f80469f4 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:16:04 +0200 Subject: [PATCH 02/46] build-time check that no AND and OR are mixed in the data api filters --- .../adapter/dataapi/opdispensers/DataApiOpDispenser.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 8bed2fcb6..d8131d146 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -26,6 +26,7 @@ import com.datastax.astra.client.core.query.Sort; import com.datastax.astra.client.core.vector.SimilarityMetric; import com.datastax.astra.client.core.query.Projection; import io.nosqlbench.adapter.dataapi.DataApiSpace; +import io.nosqlbench.nb.api.errors.OpConfigError; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; import io.nosqlbench.adapters.api.activityimpl.BaseOpDispenser; import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter; @@ -79,6 +80,12 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser logger.error(() -> "Conjunction " + filterFields.get("conjunction") + " not supported"); } } + if (!andFilterList.isEmpty() && !orFilterList.isEmpty()) { + throw new OpConfigError( + "filters list mixes 'and' and 'or' conjunctions, which is not supported; " + + "use only one conjunction type per filters list" + ); + } if (!andFilterList.isEmpty()) filter = Filters.and(andFilterList.toArray(new Filter[0])); if (!orFilterList.isEmpty()) From f68d0b2be3546e197db16773e311c5da32dc501b Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:43:38 +0200 Subject: [PATCH 03/46] bump data api client to 2.3.0 --- nb-adapters/adapter-dataapi/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nb-adapters/adapter-dataapi/pom.xml b/nb-adapters/adapter-dataapi/pom.xml index 2630f0d61..2f4ab31b5 100644 --- a/nb-adapters/adapter-dataapi/pom.xml +++ b/nb-adapters/adapter-dataapi/pom.xml @@ -49,7 +49,7 @@ com.datastax.astra astra-db-java - 2.1.4 + 2.3.0 From c054d59075335e3f964ab0f9fbd21b4e54c66af3 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 27 Jul 2026 17:22:37 +0200 Subject: [PATCH 04/46] asc/desc sort and vector sort are handled by one and the same getSortFromOp shared utility --- ...DataApiCollectionDeleteOneOpDispenser.java | 16 ++-------- ...CollectionFindOneAndDeleteOpDispenser.java | 6 ++-- ...ollectionFindOneAndReplaceOpDispenser.java | 11 ++----- .../DataApiCollectionFindOneOpDispenser.java | 9 ++---- .../DataApiCollectionFindOpDispenser.java | 11 ++----- ...DataApiCollectionUpdateOneOpDispenser.java | 11 ++----- .../opdispensers/DataApiOpDispenser.java | 30 +++++++++++++++---- 7 files changed, 43 insertions(+), 51 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java index eba8b453a..a2e9a4fef 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java @@ -55,23 +55,13 @@ public class DataApiCollectionDeleteOneOpDispenser extends DataApiOpDispenser { private CollectionDeleteOneOptions getCollectionDeleteOneOptions(ParsedOp op, long l) { CollectionDeleteOneOptions options = new CollectionDeleteOneOptions(); - Sort sort = getSortFromOp(op, l); - float[] vector = getVectorFromOp(op, l); - if (sort != null) { - options = (vector != null) ? options.sort(Sort.vector(vector), sort) : options.sort(sort); - } else if (vector != null) { - options = options.sort(Sort.vector(vector)); + Sort[] sorts = getSortFromOp(op, l); + if (sorts.length > 0) { + options = options.sort(sorts); } return options; } - private float[] getVectorFromOp(ParsedOp op, long l) { - if (op.isDefined("vector")) { - return getVectorValues(op.get("vector", l)); - } - return null; - } - @Override public DataApiBaseOp getOp(long cycle) { return opFunction.apply(cycle); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java index fd8fc11a5..195ca1f1d 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java @@ -56,9 +56,9 @@ public class DataApiCollectionFindOneAndDeleteOpDispenser extends DataApiOpDispe private CollectionFindOneAndDeleteOptions getCollectionFindOneAndDeleteOptions(ParsedOp op, long l) { CollectionFindOneAndDeleteOptions options = new CollectionFindOneAndDeleteOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = getSortFromOp(op, l); + if (sorts.length > 0) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java index d8c8937c9..9228d2fca 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java @@ -63,14 +63,9 @@ public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDisp private CollectionFindOneAndReplaceOptions getCollectionFindOneAndReplaceOptions(ParsedOp op, long l) { CollectionFindOneAndReplaceOptions options = new CollectionFindOneAndReplaceOptions(); - Sort sort = getSortFromOp(op, l); - if (op.isDefined("vector")) { - float[] vector = getVectorValues(op, l); - if (sort != null) { - options = vector != null ? options.sort(Sort.vector(vector), sort) : options.sort(sort); - } else if (vector != null) { - options = options.sort(Sort.vector(vector)); - } + Sort[] sorts = getSortFromOp(op, l); + if (sorts.length > 0) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java index 23379ff36..d0919189b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java @@ -54,12 +54,9 @@ public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { private CollectionFindOneOptions getCollectionFindOneOptions(ParsedOp op, long l) { CollectionFindOneOptions options = new CollectionFindOneOptions(); - Sort sort = getSortFromOp(op, l); - float[] vector = getVectorValues(op, l); - if (sort != null) { - options = vector != null ? options.sort(Sort.vector(vector), sort) : options.sort(sort); - } else if (vector != null) { - options = options.sort(Sort.vector(vector)); + Sort[] sorts = getSortFromOp(op, l); + if (sorts.length > 0) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java index 561ee4b61..188b3ab87 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java @@ -55,14 +55,9 @@ public class DataApiCollectionFindOpDispenser extends DataApiOpDispenser { private CollectionFindOptions getCollectionFindOptions(ParsedOp op, long l) { CollectionFindOptions options = new CollectionFindOptions(); - Sort sort = getSortFromOp(op, l); - if (op.isDefined("vector")) { - float[] vector = getVectorValues(op, l); - if (sort != null) { - options = vector != null ? options.sort(Sort.vector(vector), sort) : options.sort(sort); - } else if (vector != null) { - options = options.sort(Sort.vector(vector)); - } + Sort[] sorts = getSortFromOp(op, l); + if (sorts.length > 0) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java index d7c26b850..c44474af7 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java @@ -60,23 +60,18 @@ public class DataApiCollectionUpdateOneOpDispenser extends DataApiOpDispenser { private CollectionUpdateOneOptions getCollectionUpdateOneOptions(ParsedOp op, long l) { CollectionUpdateOneOptions options = new CollectionUpdateOneOptions(); - Sort sort = getSortFromOp(op, l); - float[] vector = getVectorFromOp(op, l); + Sort[] sorts = getSortFromOp(op, l); Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); if (upsertFunction.isPresent()) { options = options.upsert(upsertFunction.get().apply(l)); } - if (sort != null) { - options = (vector != null) ? options.sort(Sort.vector(vector), sort) : options.sort(sort); + if (sorts.length > 0) { + options = options.sort(sorts); } return options; } - private float[] getVectorFromOp(ParsedOp op, long l) { - return getVectorValues(op.get("vector", l)); - } - @Override public DataApiBaseOp getOp(long cycle) { return opFunction.apply(cycle); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index d8131d146..85bd21fa4 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -46,19 +46,37 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> sortFunction = op.getAsOptionalFunction("sort", Map.class); if (sortFunction.isPresent()) { Map sortFields = sortFunction.get().apply(l); String sortOrder = sortFields.get("type").toString(); String sortField = sortFields.get("field").toString(); switch(sortOrder) { - case "asc" -> sort = Sort.ascending(sortField); - case "desc" -> sort = Sort.descending(sortField); + case "asc" -> fieldSort = Sort.ascending(sortField); + case "desc" -> fieldSort = Sort.descending(sortField); } } - return sort; + + Sort vectorSort = null; + if (op.isDefined("vector")) { + float[] vector = getVectorValues(op, l); + if (vector != null) { + vectorSort = Sort.vector(vector); + } + } + + if (fieldSort != null && vectorSort != null) { + return new Sort[]{vectorSort, fieldSort}; + } + if (vectorSort != null) { + return new Sort[]{vectorSort}; + } + if (fieldSort != null) { + return new Sort[]{fieldSort}; + } + return new Sort[0]; } protected Filter getFilterFromOp(ParsedOp op, long l) { @@ -174,6 +192,8 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser Date: Mon, 27 Jul 2026 17:22:52 +0200 Subject: [PATCH 05/46] add package-info.java for data api adapter --- .../adapter/dataapi/package-info.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/package-info.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/package-info.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/package-info.java new file mode 100644 index 000000000..72fd85a32 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/// This package is the top-level entry point for the NoSQLBench Data API adapter (`dataapi`). +/// It wires together the standard adapter architecture: +/// {@link io.nosqlbench.adapter.dataapi.DataApiDriverAdapter} (registered via `@Service`), +/// {@link io.nosqlbench.adapter.dataapi.DataApiOpMapper} (dispatches to per-op dispensers), +/// and {@link io.nosqlbench.adapter.dataapi.DataApiSpace} (holds the driver client state). +/// +/// Op dispensers live in the `opdispensers` sub-package; their corresponding runnable ops +/// live in the `ops` sub-package. +package io.nosqlbench.adapter.dataapi; From 8768ea784384e52f8d8afd2865a50241b19cce6d Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 27 Jul 2026 17:27:07 +0200 Subject: [PATCH 06/46] getSortFromOp always validates against the ascdesc+vector illegal double-sort and returns at most one --- .../DataApiCollectionDeleteOneOpDispenser.java | 6 +++--- ...DataApiCollectionFindOneAndDeleteOpDispenser.java | 6 +++--- ...ataApiCollectionFindOneAndReplaceOpDispenser.java | 6 +++--- .../DataApiCollectionFindOneOpDispenser.java | 6 +++--- .../DataApiCollectionFindOpDispenser.java | 6 +++--- .../DataApiCollectionUpdateOneOpDispenser.java | 8 ++++---- .../dataapi/opdispensers/DataApiOpDispenser.java | 12 +++++++----- 7 files changed, 26 insertions(+), 24 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java index a2e9a4fef..f0ee8c2be 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionDeleteOneOpDispenser extends DataApiOpDispenser { private CollectionDeleteOneOptions getCollectionDeleteOneOptions(ParsedOp op, long l) { CollectionDeleteOneOptions options = new CollectionDeleteOneOptions(); - Sort[] sorts = getSortFromOp(op, l); - if (sorts.length > 0) { - options = options.sort(sorts); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java index 195ca1f1d..fd8fc11a5 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java @@ -56,9 +56,9 @@ public class DataApiCollectionFindOneAndDeleteOpDispenser extends DataApiOpDispe private CollectionFindOneAndDeleteOptions getCollectionFindOneAndDeleteOptions(ParsedOp op, long l) { CollectionFindOneAndDeleteOptions options = new CollectionFindOneAndDeleteOptions(); - Sort[] sorts = getSortFromOp(op, l); - if (sorts.length > 0) { - options = options.sort(sorts); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java index 9228d2fca..42f5f631f 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java @@ -63,9 +63,9 @@ public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDisp private CollectionFindOneAndReplaceOptions getCollectionFindOneAndReplaceOptions(ParsedOp op, long l) { CollectionFindOneAndReplaceOptions options = new CollectionFindOneAndReplaceOptions(); - Sort[] sorts = getSortFromOp(op, l); - if (sorts.length > 0) { - options = options.sort(sorts); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java index d0919189b..01dec8766 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java @@ -54,9 +54,9 @@ public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { private CollectionFindOneOptions getCollectionFindOneOptions(ParsedOp op, long l) { CollectionFindOneOptions options = new CollectionFindOneOptions(); - Sort[] sorts = getSortFromOp(op, l); - if (sorts.length > 0) { - options = options.sort(sorts); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java index 188b3ab87..93a57b7ca 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionFindOpDispenser extends DataApiOpDispenser { private CollectionFindOptions getCollectionFindOptions(ParsedOp op, long l) { CollectionFindOptions options = new CollectionFindOptions(); - Sort[] sorts = getSortFromOp(op, l); - if (sorts.length > 0) { - options = options.sort(sorts); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java index c44474af7..d5748e909 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java @@ -60,15 +60,15 @@ public class DataApiCollectionUpdateOneOpDispenser extends DataApiOpDispenser { private CollectionUpdateOneOptions getCollectionUpdateOneOptions(ParsedOp op, long l) { CollectionUpdateOneOptions options = new CollectionUpdateOneOptions(); - Sort[] sorts = getSortFromOp(op, l); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); if (upsertFunction.isPresent()) { options = options.upsert(upsertFunction.get().apply(l)); } - if (sorts.length > 0) { - options = options.sort(sorts); - } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 85bd21fa4..90399aa52 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -46,7 +46,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> sortFunction = op.getAsOptionalFunction("sort", Map.class); if (sortFunction.isPresent()) { @@ -68,15 +68,17 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser Date: Mon, 27 Jul 2026 18:35:09 +0200 Subject: [PATCH 07/46] TEMPorarily instrument Data API client to debug-log requests/responses --- .../java/io/nosqlbench/adapter/dataapi/DataApiSpace.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java index 5f579c203..b38d419e9 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java @@ -20,6 +20,9 @@ import com.datastax.astra.client.DataAPIClient; import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.admin.AstraDBAdmin; import com.datastax.astra.client.admin.DatabaseAdmin; +// TODO: remove this - it's to log Data API requests and responses +import com.datastax.astra.client.core.options.DataAPIClientOptions; + import io.nosqlbench.adapters.api.activityimpl.uniform.BaseSpace; import io.nosqlbench.nb.api.config.standard.ConfigModel; import io.nosqlbench.nb.api.config.standard.NBConfigModel; @@ -75,7 +78,11 @@ public class DataApiSpace extends BaseSpace { } private void createClient() { - this.dataAPIClient = new DataAPIClient(astraToken); + // TODO: remove this - it's to log Data API requests and responses + DataAPIClientOptions options = new DataAPIClientOptions() + .logRequests(); + + this.dataAPIClient = new DataAPIClient(astraToken, /* S */ options); if (namespace != null) { this.database = dataAPIClient.getDatabase(astraApiEndpoint, namespace); } else { From e5cafec8d9faea0f58b627a36b8fa805e0db1feb Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 28 Jul 2026 17:06:28 +0200 Subject: [PATCH 08/46] align DataAPIOpType enum and the corresponding op mapper case clauses --- .../adapter/dataapi/ops/DataApiOpType.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index a9c8370ae..b260e10d6 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -17,7 +17,22 @@ package io.nosqlbench.adapter.dataapi.ops; public enum DataApiOpType { + // admin ops: + create_database, + list_databases, + drop_database, + get_database_info, + // db-admin ops: + create_namespace, + list_namespaces, + drop_namespace, + // in-database ops: create_collection, + delete_collection, + list_collections, + list_collection_names, + create_collection_with_class, + // in-collection ops: insert_many, insert_one, insert_one_vector, @@ -31,9 +46,6 @@ public enum DataApiOpType { update_many, delete_one, delete_many, - delete_collection, - list_collections, - list_collection_names, estimated_document_count, find_by_id, find_distinct, @@ -41,12 +53,4 @@ public enum DataApiOpType { replace_one, find_one_and_replace, delete_all, - create_collection_with_class, - create_database, - list_databases, - drop_database, - get_database_info, - create_namespace, - list_namespaces, - drop_namespace, } From 0faa7d7e46ee2914808021e68697e4c4865de90a Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 28 Jul 2026 17:43:27 +0200 Subject: [PATCH 09/46] remove create_collection_with_class and find_distinct out-of-scope data api operations --- .../adapter/dataapi/DataApiOpMapper.java | 16 ++--- ...aApiCollectionFindDistinctOpDispenser.java | 67 ------------------- ...iCreateCollectionWithClassOpDispenser.java | 61 ----------------- .../ops/DataApiCollectionFindDistinctOp.java | 41 ------------ .../DataApiCreateCollectionWithClassOp.java | 38 ----------- .../adapter/dataapi/ops/DataApiOpType.java | 14 ++-- 6 files changed, 13 insertions(+), 224 deletions(-) delete mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindDistinctOpDispenser.java delete mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionWithClassOpDispenser.java delete mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindDistinctOp.java delete mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCreateCollectionWithClassOp.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 42efd195d..2d0a420ab 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -63,29 +63,27 @@ public class DataApiOpMapper implements OpMapper { case list_collections -> new DataApiListCollectionsOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collection_names -> new DataApiListCollectionNamesOpDispenser(adapter, op, typeAndTarget.targetFunction); - case create_collection_with_class -> new DataApiCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector -> new DataApiCollectionFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector_filter -> new DataApiCollectionFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_by_id -> new DataApiCollectionFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); - case estimated_document_count -> - new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_by_id -> new DataApiCollectionFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_distinct -> new DataApiCollectionFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); - case count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); + case delete_all -> new DataApiCollectionDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); - case delete_all -> new DataApiCollectionDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); + case estimated_document_count -> + new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); + case count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindDistinctOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindDistinctOpDispenser.java deleted file mode 100644 index cc20848e0..000000000 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindDistinctOpDispenser.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) nosqlbench - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package io.nosqlbench.adapter.dataapi.opdispensers; - -import com.datastax.astra.client.databases.Database; -import com.datastax.astra.client.core.query.Filter; -import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; -import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindDistinctOp; -import io.nosqlbench.adapters.api.templating.ParsedOp; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.function.LongFunction; - -public class DataApiCollectionFindDistinctOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionFindDistinctOpDispenser.class); - private final LongFunction opFunction; - public DataApiCollectionFindDistinctOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { - super(adapter, op, targetFunction); - this.opFunction = createOpFunction(op); - } - - private LongFunction createOpFunction(ParsedOp op) { - return (l) -> { - Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getFilterFromOp(op, l); - Class targetClass = getTargetClass(op, l); - return new DataApiCollectionFindDistinctOp( - db, - db.getCollection(targetFunction.apply(l)), - op.getAsRequiredFunction("fieldName", String.class).apply(l), - filter, - targetClass - ); - }; - } - - private Class getTargetClass(ParsedOp op, long l) { - String className = op.getAsFunctionOr("resultClass", "java.lang.String").apply(l); - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - @Override - public DataApiBaseOp getOp(long cycle) { - return opFunction.apply(cycle); - } -} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionWithClassOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionWithClassOpDispenser.java deleted file mode 100644 index 76aca2e7a..000000000 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionWithClassOpDispenser.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) nosqlbench - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.nosqlbench.adapter.dataapi.opdispensers; - -import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; -import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCreateCollectionWithClassOp; -import io.nosqlbench.adapters.api.templating.ParsedOp; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.function.LongFunction; - -public class DataApiCreateCollectionWithClassOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCreateCollectionWithClassOpDispenser.class); - private final LongFunction opFunction; - - public DataApiCreateCollectionWithClassOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { - super(adapter, op, targetFunction); - this.opFunction = createOpFunction(op); - } - - private LongFunction createOpFunction(ParsedOp op) { - return (l) -> new DataApiCreateCollectionWithClassOp( - spaceFunction.apply(l).getDatabase(), - targetFunction.apply(l), - this.getCollectionDefinitionFromOp(op, l), - getCreateClass(op, l) - ); - } - - private Class getCreateClass(ParsedOp op, long l) { - String className = op.getAsFunctionOr("createClass", "com.datastax.astra.client.collections.definition.documents.Document").apply(l); - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - @Override - public DataApiBaseOp getOp(long cycle) { - return opFunction.apply(cycle); - } - - -} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindDistinctOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindDistinctOp.java deleted file mode 100644 index 4c9aa78d8..000000000 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindDistinctOp.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) nosqlbench - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.nosqlbench.adapter.dataapi.ops; - -import com.datastax.astra.client.collections.Collection; -import com.datastax.astra.client.databases.Database; -import com.datastax.astra.client.core.query.Filter; - -public class DataApiCollectionFindDistinctOp extends DataApiBaseOp { - private final Collection collection; - private final String fieldName; - private final Filter filter; - private final Class resultClass; - - public DataApiCollectionFindDistinctOp(Database db, Collection collection, String fieldName, Filter filter, Class resultClass) { - super(db); - this.collection = collection; - this.fieldName = fieldName; - this.filter = filter; - this.resultClass = resultClass; - } - - @Override - public Object apply(long value) { - return collection.distinct(fieldName, filter, resultClass); - } -} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCreateCollectionWithClassOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCreateCollectionWithClassOp.java deleted file mode 100644 index 4d21bbc57..000000000 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCreateCollectionWithClassOp.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) nosqlbench - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.nosqlbench.adapter.dataapi.ops; - -import com.datastax.astra.client.databases.Database; -import com.datastax.astra.client.collections.definition.CollectionDefinition; - -public class DataApiCreateCollectionWithClassOp extends DataApiBaseOp { - private final String collectionName; - private final CollectionDefinition definition; - private final Class clazz; - - public DataApiCreateCollectionWithClassOp(Database db, String collectionName, CollectionDefinition definition, Class clazz) { - super(db); - this.collectionName = collectionName; - this.definition = definition; - this.clazz = clazz; - } - - @Override - public Object apply(long value) { - return db.createCollection(collectionName, definition, clazz); - } -} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index b260e10d6..1fb8a92f4 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -31,26 +31,24 @@ public enum DataApiOpType { delete_collection, list_collections, list_collection_names, - create_collection_with_class, // in-collection ops: insert_many, insert_one, insert_one_vector, find, find_one, - find_one_and_delete, - find_one_and_update, find_vector, find_vector_filter, + find_by_id, update_one, + find_one_and_update, update_many, delete_one, + find_one_and_delete, delete_many, - estimated_document_count, - find_by_id, - find_distinct, - count_documents, + delete_all, replace_one, find_one_and_replace, - delete_all, + estimated_document_count, + count_documents, } From 4128a7c41dcb131bfaaa6bb85fee7456abf50ad9 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Wed, 29 Jul 2026 17:51:56 +0200 Subject: [PATCH 10/46] find_one_and_update accepts non-doubles for inc and min --- .../adapter/dataapi/opdispensers/DataApiOpDispenser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 90399aa52..eee2cdd82 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -158,12 +158,12 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser update = Updates.set(updateFields.get("field").toString(), updateFields.get("value")); case "inc" -> - update = Updates.inc(updateFields.get("field").toString(), (double) updateFields.get("value")); + update = Updates.inc(updateFields.get("field").toString(), ((Number) updateFields.get("value")).doubleValue()); case "unset" -> update = Updates.unset(updateFields.get("field").toString()); case "addToSet" -> update = Updates.addToSet(updateFields.get("field").toString(), updateFields.get("value")); case "min" -> - update = Updates.min(updateFields.get("field").toString(), (double) updateFields.get("value")); + update = Updates.min(updateFields.get("field").toString(), ((Number) updateFields.get("value")).doubleValue()); case "rename" -> update = Updates.rename(updateFields.get("field").toString(), updateFields.get("value").toString()); default -> logger.error(() -> "Operation " + updateFields.get("operation") + " not supported"); From fcd8d9a35ee5234855905cbd12e9b6343dd7879a Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:07:10 +0200 Subject: [PATCH 11/46] expand the find_one_and_update syntax: legacy 'updates:update:...' with deprecation + new reasonable syntax --- ...CollectionFindOneAndUpdateOpDispenser.java | 2 +- .../opdispensers/DataApiOpDispenser.java | 73 ++++++++++++------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java index 2bbd2df21..ea0f942d2 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java @@ -40,7 +40,7 @@ public class DataApiCollectionFindOneAndUpdateOpDispenser extends DataApiOpDispe return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getFilterFromOp(op, l); - Update update = getUpdates(op, l); + Update update = getUpdateFromOp(op, l); return new DataApiCollectionFindOneAndUpdateOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index eee2cdd82..d65f0746b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -21,7 +21,6 @@ import com.datastax.astra.client.core.query.Filters; import com.datastax.astra.client.collections.definition.CollectionDefinition; import com.datastax.astra.client.collections.definition.CollectionDefaultIdTypes; import com.datastax.astra.client.collections.commands.Update; -import com.datastax.astra.client.collections.commands.Updates; import com.datastax.astra.client.core.query.Sort; import com.datastax.astra.client.core.vector.SimilarityMetric; import com.datastax.astra.client.core.query.Projection; @@ -38,6 +37,7 @@ import java.util.function.LongFunction; public abstract class DataApiOpDispenser extends BaseOpDispenser { protected final LongFunction targetFunction; protected final LongFunction spaceFunction; + private volatile boolean warnedDeprecatedUpdates = false; protected DataApiOpDispenser(DriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { @@ -146,36 +146,57 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> updatesFunction = op.getAsOptionalFunction("updates", Map.class); - if (updatesFunction.isPresent()) { - Map updates = updatesFunction.get().apply(l); - for (Map.Entry entry : updates.entrySet()) { - if (entry.getKey().equalsIgnoreCase("update")) { - Map updateFields = (Map) entry.getValue(); - switch (updateFields.get("operation").toString()) { - case "set" -> - update = Updates.set(updateFields.get("field").toString(), updateFields.get("value")); - case "inc" -> - update = Updates.inc(updateFields.get("field").toString(), ((Number) updateFields.get("value")).doubleValue()); - case "unset" -> update = Updates.unset(updateFields.get("field").toString()); - case "addToSet" -> - update = Updates.addToSet(updateFields.get("field").toString(), updateFields.get("value")); - case "min" -> - update = Updates.min(updateFields.get("field").toString(), ((Number) updateFields.get("value")).doubleValue()); - case "rename" -> - update = Updates.rename(updateFields.get("field").toString(), updateFields.get("value").toString()); - default -> logger.error(() -> "Operation " + updateFields.get("operation") + " not supported"); - } - } else { - logger.error(() -> "Filter " + entry.getKey() + " not supported"); - } + @SuppressWarnings("unchecked") + protected Update getUpdateFromOp(ParsedOp op, long l) { + Update update = Update.create(); + Object rawUpdates = op.getAsOptionalFunction("updates", Object.class) + .map(f -> f.apply(l)) + .orElse(null); + if (rawUpdates instanceof List rawList) { + // New form: updates is a list of {operation, field, value} entries + List> updatesList = (List>) rawList; + for (Map entry : updatesList) { + String operation = entry.get("operation").toString(); + String field = entry.get("field").toString(); + Object value = entry.get("value"); + applyUpdateOperation(update, operation, field, value); + } + } else if (rawUpdates instanceof Map rawMap) { + /* Backward-compatibility with the previous single-update form: + updates: + update: + operation: inc + field: myfield + value: 21474 + */ + if (!warnedDeprecatedUpdates) { + warnedDeprecatedUpdates = true; + logger.warn(() -> "DEPRECATED: 'updates' as a map with a nested 'update' key is deprecated. " + + "Use a list of operation entries instead (see op template documentation)."); + } + Map updateFields = (Map) ((Map) rawMap).get("update"); + if (updateFields != null) { + applyUpdateOperation(update, + updateFields.get("operation").toString(), + updateFields.get("field").toString(), + updateFields.get("value")); } } return update; } + private void applyUpdateOperation(Update update, String operation, String field, Object value) { + switch (operation) { + case "set" -> update.set(field, value); + case "inc" -> update.inc(field, ((Number) value).doubleValue()); + case "unset" -> update.unset(field); + case "addToSet" -> update.addToSet(field, value); + case "min" -> update.min(field, ((Number) value).doubleValue()); + case "rename" -> update.rename(field, value.toString()); + default -> logger.error(() -> "Operation '" + operation + "' not supported"); + } + } + protected float[] getVectorValues(ParsedOp op, long l) { Object rawVectorValues = op.get("vector", l); return getVectorValues(rawVectorValues); From 9a634d7da9a9c2c33a3452cd951e1bfeb9605b82 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:52:03 +0200 Subject: [PATCH 12/46] introduced getUpsertFromOp; enable upsert and sort in find_one_and_update --- ...CollectionFindOneAndUpdateOpDispenser.java | 21 ++++++++++++++++++- .../opdispensers/DataApiOpDispenser.java | 9 ++++++++ .../DataApiCollectionFindOneAndUpdateOp.java | 7 +++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java index ea0f942d2..0c33f1faf 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java @@ -18,7 +18,11 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.core.query.Sort; import com.datastax.astra.client.collections.commands.Update; +import com.datastax.astra.client.collections.commands.options.CollectionDeleteOneOptions; +import com.datastax.astra.client.collections.commands.options.CollectionFindOneAndUpdateOptions; + import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOneAndUpdateOp; @@ -41,16 +45,31 @@ public class DataApiCollectionFindOneAndUpdateOpDispenser extends DataApiOpDispe Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getFilterFromOp(op, l); Update update = getUpdateFromOp(op, l); + CollectionFindOneAndUpdateOptions options = getCollectionFindOneAndUpdateOptions(op, l); return new DataApiCollectionFindOneAndUpdateOp( db, db.getCollection(targetFunction.apply(l)), filter, - update + update, + options ); }; } + private CollectionFindOneAndUpdateOptions getCollectionFindOneAndUpdateOptions(ParsedOp op, long l) { + CollectionFindOneAndUpdateOptions options = new CollectionFindOneAndUpdateOptions(); + Sort sort = getSortFromOp(op, l); + Boolean upsert = getUpsertFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + if ( upsert != null ){ + options = options.upsert(upsert); + } + return options; + } + @Override public DataApiBaseOp getOp(long cycle) { return opFunction.apply(cycle); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index d65f0746b..133188036 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -257,6 +257,15 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); + if (upsertFunction.isPresent()) { + LongFunction uf = upsertFunction.get(); + return uf.apply(l); + } + return null; + } + protected CollectionDefinition getCollectionDefinitionFromOp(ParsedOp op, long l) { CollectionDefinition optionsBldr = new CollectionDefinition(); Optional> dimFunc = op.getAsOptionalFunction("dimensions", Integer.class); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOneAndUpdateOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOneAndUpdateOp.java index bae98b30c..d38c26d4a 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOneAndUpdateOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOneAndUpdateOp.java @@ -21,21 +21,24 @@ import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.collections.definition.documents.Document; import com.datastax.astra.client.core.query.Filter; import com.datastax.astra.client.collections.commands.Update; +import com.datastax.astra.client.collections.commands.options.CollectionFindOneAndUpdateOptions; public class DataApiCollectionFindOneAndUpdateOp extends DataApiBaseOp { private final Collection collection; private final Filter filter; private final Update update; + private final CollectionFindOneAndUpdateOptions options; - public DataApiCollectionFindOneAndUpdateOp(Database db, Collection collection, Filter filter, Update update) { + public DataApiCollectionFindOneAndUpdateOp(Database db, Collection collection, Filter filter, Update update, CollectionFindOneAndUpdateOptions options) { super(db); this.collection = collection; this.filter = filter; this.update = update; + this.options = options; } @Override public Object apply(long value) { - return collection.findOneAndUpdate(filter, update); + return collection.findOneAndUpdate(filter, update, options); } } From abd8322b516b968537adfc1a3fc9ccfc1492a834 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Fri, 31 Jul 2026 18:14:53 +0200 Subject: [PATCH 13/46] restored all legacy ops from main; full split f1upd/legacy f1upd --- .../adapter/dataapi/DataApiOpMapper.java | 7 +- ...llectionLegacyFindDistinctOpDispenser.java | 67 +++++++++++++++ ...tionLegacyFindOneAndUpdateOpDispenser.java | 76 ++++++++++++++++ .../DataApiCreateCollectionOpDispenser.java | 2 +- ...yCreateCollectionWithClassOpDispenser.java | 61 +++++++++++++ .../opdispensers/DataApiOpDispenser.java | 86 +++++++++++-------- ...DataApiCollectionLegacyFindDistinctOp.java | 41 +++++++++ ...ApiCollectionLegacyFindOneAndUpdateOp.java | 44 ++++++++++ ...piDbLegacyCreateCollectionWithClassOp.java | 38 ++++++++ .../adapter/dataapi/ops/DataApiOpType.java | 9 ++ 10 files changed, 394 insertions(+), 37 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbLegacyCreateCollectionWithClassOpDispenser.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOneAndUpdateOp.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbLegacyCreateCollectionWithClassOp.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 2d0a420ab..a0123d0be 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -48,6 +48,7 @@ public class DataApiOpMapper implements OpMapper { ); logger.debug(() -> "Using '" + typeAndTarget.enumId + "' op type for op template '" + op.getName() + "'"); return switch (typeAndTarget.enumId) { + // LEGACY OPS // admin ops: case create_database -> new DataApiCreateDatabaseOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_databases -> new DataApiListDatabasesOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -59,6 +60,7 @@ public class DataApiOpMapper implements OpMapper { case drop_namespace -> new DataApiDropNamespaceOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-database ops: case create_collection -> new DataApiCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); + case create_collection_with_class -> new DataApiDbLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_collection -> new DataApiDropCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collections -> new DataApiListCollectionsOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collection_names -> @@ -68,12 +70,13 @@ public class DataApiOpMapper implements OpMapper { case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector -> new DataApiCollectionFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector_filter -> new DataApiCollectionFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_by_id -> new DataApiCollectionFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -84,6 +87,8 @@ public class DataApiOpMapper implements OpMapper { case estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); case count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); + // NEW-STYLE OPS + case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java new file mode 100644 index 000000000..952b0e438 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyFindDistinctOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyFindDistinctOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindDistinctOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionLegacyFindDistinctOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getFilterFromOp(op, l); + Class targetClass = getTargetClass(op, l); + return new DataApiCollectionLegacyFindDistinctOp( + db, + db.getCollection(targetFunction.apply(l)), + op.getAsRequiredFunction("fieldName", String.class).apply(l), + filter, + targetClass + ); + }; + } + + private Class getTargetClass(ParsedOp op, long l) { + String className = op.getAsFunctionOr("resultClass", "java.lang.String").apply(l); + try { + return Class.forName(className); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java new file mode 100644 index 000000000..d49fb79bd --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.core.query.Sort; +import com.datastax.astra.client.collections.commands.Update; +import com.datastax.astra.client.collections.commands.options.CollectionFindOneAndUpdateOptions; + +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyFindOneAndUpdateOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyFindOneAndUpdateOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindOneAndUpdateOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionLegacyFindOneAndUpdateOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getFilterFromOp(op, l); + Update update = getLegacyUpdateFromOp(op, l); + CollectionFindOneAndUpdateOptions options = getCollectionLegacyFindOneAndUpdateOptions(op, l); + + return new DataApiCollectionLegacyFindOneAndUpdateOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + update, + options + ); + }; + } + + private CollectionFindOneAndUpdateOptions getCollectionLegacyFindOneAndUpdateOptions(ParsedOp op, long l) { + CollectionFindOneAndUpdateOptions options = new CollectionFindOneAndUpdateOptions(); + Sort sort = getSortFromOp(op, l); + Boolean upsert = getUpsertFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + if ( upsert != null ){ + options = options.upsert(upsert); + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java index 92b1f38d6..7c4006781 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java @@ -41,7 +41,7 @@ public class DataApiCreateCollectionOpDispenser extends DataApiOpDispenser { new DataApiCreateCollectionOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), - this.getCollectionDefinitionFromOp(op, l) + this.getLegacyCollectionDefinitionFromOp(op, l) ); return dataApiCreateCollectionOp; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbLegacyCreateCollectionWithClassOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbLegacyCreateCollectionWithClassOpDispenser.java new file mode 100644 index 000000000..bf9cfaca2 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbLegacyCreateCollectionWithClassOpDispenser.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiDbLegacyCreateCollectionWithClassOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiDbLegacyCreateCollectionWithClassOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiDbLegacyCreateCollectionWithClassOpDispenser.class); + private final LongFunction opFunction; + + public DataApiDbLegacyCreateCollectionWithClassOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> new DataApiDbLegacyCreateCollectionWithClassOp( + spaceFunction.apply(l).getDatabase(), + targetFunction.apply(l), + this.getLegacyCollectionDefinitionFromOp(op, l), + getCreateClass(op, l) + ); + } + + private Class getCreateClass(ParsedOp op, long l) { + String className = op.getAsFunctionOr("createClass", "com.datastax.astra.client.collections.definition.documents.Document").apply(l); + try { + return Class.forName(className); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } + + +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 133188036..3c17f5a32 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -21,6 +21,7 @@ import com.datastax.astra.client.core.query.Filters; import com.datastax.astra.client.collections.definition.CollectionDefinition; import com.datastax.astra.client.collections.definition.CollectionDefaultIdTypes; import com.datastax.astra.client.collections.commands.Update; +import com.datastax.astra.client.collections.commands.Updates; import com.datastax.astra.client.core.query.Sort; import com.datastax.astra.client.core.vector.SimilarityMetric; import com.datastax.astra.client.core.query.Projection; @@ -37,7 +38,6 @@ import java.util.function.LongFunction; public abstract class DataApiOpDispenser extends BaseOpDispenser { protected final LongFunction targetFunction; protected final LongFunction spaceFunction; - private volatile boolean warnedDeprecatedUpdates = false; protected DataApiOpDispenser(DriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { @@ -146,41 +146,18 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser f.apply(l)) - .orElse(null); - if (rawUpdates instanceof List rawList) { - // New form: updates is a list of {operation, field, value} entries - List> updatesList = (List>) rawList; - for (Map entry : updatesList) { - String operation = entry.get("operation").toString(); - String field = entry.get("field").toString(); - Object value = entry.get("value"); - applyUpdateOperation(update, operation, field, value); - } - } else if (rawUpdates instanceof Map rawMap) { - /* Backward-compatibility with the previous single-update form: - updates: - update: - operation: inc - field: myfield - value: 21474 - */ - if (!warnedDeprecatedUpdates) { - warnedDeprecatedUpdates = true; - logger.warn(() -> "DEPRECATED: 'updates' as a map with a nested 'update' key is deprecated. " + - "Use a list of operation entries instead (see op template documentation)."); - } - Map updateFields = (Map) ((Map) rawMap).get("update"); - if (updateFields != null) { - applyUpdateOperation(update, - updateFields.get("operation").toString(), - updateFields.get("field").toString(), - updateFields.get("value")); - } + Optional> updatesFunction = op.getAsOptionalFunction("updates", List.class); + @SuppressWarnings("unchecked") + List> updatesList = updatesFunction + .map(f -> (List>) f.apply(l)) + .orElse(List.of()); + for (Map entry : updatesList) { + String operation = entry.get("operation").toString(); + String field = entry.get("field").toString(); + Object value = entry.get("value"); + applyUpdateOperation(update, operation, field, value); } return update; } @@ -266,7 +243,46 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> updatesFunction = op.getAsOptionalFunction("updates", Map.class); + if (updatesFunction.isPresent()) { + Map updates = updatesFunction.get().apply(l); + for (Map.Entry entry : updates.entrySet()) { + if (entry.getKey().equalsIgnoreCase("update")) { + Map updateFields = (Map) entry.getValue(); + switch (updateFields.get("operation").toString()) { + case "set" -> + update = Updates.set(updateFields.get("field").toString(), updateFields.get("value")); + case "inc" -> + update = Updates.inc(updateFields.get("field").toString(), ((Number) updateFields.get("value")).doubleValue()); + case "unset" -> update = Updates.unset(updateFields.get("field").toString()); + case "addToSet" -> + update = Updates.addToSet(updateFields.get("field").toString(), updateFields.get("value")); + case "min" -> + update = Updates.min(updateFields.get("field").toString(), ((Number) updateFields.get("value")).doubleValue()); + case "rename" -> + update = Updates.rename(updateFields.get("field").toString(), updateFields.get("value").toString()); + default -> logger.error(() -> "Operation " + updateFields.get("operation") + " not supported"); + } + } else { + logger.error(() -> "Unsupported entry under 'updates': '" + entry.getKey() + "'"); + } + } + } + return update; + } + + protected CollectionDefinition getLegacyCollectionDefinitionFromOp(ParsedOp op, long l) { CollectionDefinition optionsBldr = new CollectionDefinition(); Optional> dimFunc = op.getAsOptionalFunction("dimensions", Integer.class); if (dimFunc.isPresent()) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java new file mode 100644 index 000000000..ed1833586 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.ops; + +import com.datastax.astra.client.collections.Collection; +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; + +public class DataApiCollectionLegacyFindDistinctOp extends DataApiBaseOp { + private final Collection collection; + private final String fieldName; + private final Filter filter; + private final Class resultClass; + + public DataApiCollectionLegacyFindDistinctOp(Database db, Collection collection, String fieldName, Filter filter, Class resultClass) { + super(db); + this.collection = collection; + this.fieldName = fieldName; + this.filter = filter; + this.resultClass = resultClass; + } + + @Override + public Object apply(long value) { + return collection.distinct(fieldName, filter, resultClass); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOneAndUpdateOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOneAndUpdateOp.java new file mode 100644 index 000000000..22c05ff40 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOneAndUpdateOp.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.ops; + +import com.datastax.astra.client.collections.Collection; +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.collections.definition.documents.Document; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.collections.commands.Update; +import com.datastax.astra.client.collections.commands.options.CollectionFindOneAndUpdateOptions; + +public class DataApiCollectionLegacyFindOneAndUpdateOp extends DataApiBaseOp { + private final Collection collection; + private final Filter filter; + private final Update update; + private final CollectionFindOneAndUpdateOptions options; + + public DataApiCollectionLegacyFindOneAndUpdateOp(Database db, Collection collection, Filter filter, Update update, CollectionFindOneAndUpdateOptions options) { + super(db); + this.collection = collection; + this.filter = filter; + this.update = update; + this.options = options; + } + + @Override + public Object apply(long value) { + return collection.findOneAndUpdate(filter, update, options); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbLegacyCreateCollectionWithClassOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbLegacyCreateCollectionWithClassOp.java new file mode 100644 index 000000000..27ddae619 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbLegacyCreateCollectionWithClassOp.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.ops; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.collections.definition.CollectionDefinition; + +public class DataApiDbLegacyCreateCollectionWithClassOp extends DataApiBaseOp { + private final String collectionName; + private final CollectionDefinition definition; + private final Class clazz; + + public DataApiDbLegacyCreateCollectionWithClassOp(Database db, String collectionName, CollectionDefinition definition, Class clazz) { + super(db); + this.collectionName = collectionName; + this.definition = definition; + this.clazz = clazz; + } + + @Override + public Object apply(long value) { + return db.createCollection(collectionName, definition, clazz); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 1fb8a92f4..bc6e12f6e 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -17,6 +17,7 @@ package io.nosqlbench.adapter.dataapi.ops; public enum DataApiOpType { + // LEGACY OPS // admin ops: create_database, list_databases, @@ -28,6 +29,7 @@ public enum DataApiOpType { drop_namespace, // in-database ops: create_collection, + create_collection_with_class, delete_collection, list_collections, list_collection_names, @@ -36,6 +38,7 @@ public enum DataApiOpType { insert_one, insert_one_vector, find, + find_distinct, find_one, find_vector, find_vector_filter, @@ -51,4 +54,10 @@ public enum DataApiOpType { find_one_and_replace, estimated_document_count, count_documents, + // NEW-STYLE OPS + // admin ops: + // db-admin ops: + // in-database ops: + // in-collection ops: + collection_find_one_and_update, } From 69313d2deb8f85c1dd50f48cdd529369e622b064 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Sat, 1 Aug 2026 22:45:05 +0200 Subject: [PATCH 14/46] switched to free-form in filter+update for (new) find_one_and_update op --- .../opdispensers/DataApiOpDispenser.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 3c17f5a32..a8c0d5517 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -50,6 +50,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> sortFunction = op.getAsOptionalFunction("sort", Map.class); if (sortFunction.isPresent()) { + @SuppressWarnings("unchecked") Map sortFields = sortFunction.get().apply(l); String sortOrder = sortFields.get("type").toString(); String sortField = sortFields.get("field").toString(); @@ -82,12 +83,19 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser filterMap = getFreeFormFromOp(op, l, "filter", false); + if (filterMap != null) { + return new Filter(filterMap); + } + return null; + /* + // TODO choose whether to switch to the free-form route (performant? viable re: bindings?) Filter filter = null; Optional> filterFunction = op.getAsOptionalFunction("filters", List.class) .or(() -> op.getAsOptionalFunction("filter",List.class)); if (filterFunction.isPresent()) { + @SuppressWarnings("unchecked") List> filters = filterFunction.get().apply(l); List andFilterList = new ArrayList<>(); List orFilterList = new ArrayList<>(); @@ -112,6 +120,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser filtersList, String operator, String fieldName, Object fieldValue) { @@ -147,6 +156,9 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser updateMap = getFreeFormFromOp(op, l, "update", true); + return new Update(updateMap); + /* TODO choose whether to switch to freeform for update Update update = Update.create(); Optional> updatesFunction = op.getAsOptionalFunction("updates", List.class); @SuppressWarnings("unchecked") @@ -160,6 +172,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser vectorValuesList = (List) rawVectorValues; vectorValues = new float[vectorValuesList.size()]; for (int i = 0; i < vectorValuesList.size(); i++) { @@ -214,6 +228,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> projectionFunction = op.getAsOptionalFunction("projection", Map.class); if (projectionFunction.isPresent()) { + @SuppressWarnings("unchecked") Map> projectionFields = projectionFunction.get().apply(l); for (Map.Entry> field : projectionFields.entrySet()) { List includeFields = field.getValue(); @@ -243,6 +258,21 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser getFreeFormFromOp(ParsedOp op, long l, String fieldName, Boolean required) { + Optional> ffMapFunc = op.getAsOptionalFunction(fieldName, Map.class); + if (ffMapFunc.isPresent()) { + LongFunction dmf = ffMapFunc.get(); + return dmf.apply(l); + } else { + if (required) { + logger.error("Required field '" + fieldName + "' not supplied."); + } + return null; + } + } + /* LEGACY OP DISPENSER UTILS START HERE */ /* @@ -256,9 +286,11 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> updatesFunction = op.getAsOptionalFunction("updates", Map.class); if (updatesFunction.isPresent()) { + @SuppressWarnings("unchecked") Map updates = updatesFunction.get().apply(l); for (Map.Entry entry : updates.entrySet()) { if (entry.getKey().equalsIgnoreCase("update")) { + @SuppressWarnings("unchecked") Map updateFields = (Map) entry.getValue(); switch (updateFields.get("operation").toString()) { case "set" -> @@ -282,6 +314,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> dimFunc = op.getAsOptionalFunction("dimensions", Integer.class); From 253a47dd7ba1e22b81536ef2c13c786fb4de7964 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:15:39 +0200 Subject: [PATCH 15/46] introduce deprecation warning for explicitly-Legacy Ops --- .../adapter/dataapi/DataApiOpMapper.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index a0123d0be..5a92fc4df 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -26,10 +26,22 @@ import io.nosqlbench.engine.api.templating.TypeAndTarget; import io.nosqlbench.nb.api.components.core.NBComponent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.HashMap; +import java.util.Map; import java.util.function.LongFunction; public class DataApiOpMapper implements OpMapper { private static final Logger logger = LogManager.getLogger(DataApiOpMapper.class); + + // Maps a deprecated op type to its replacement, or null if there is no replacement. + private static final Map DEPRECATED_OP_TYPES; + static { + DEPRECATED_OP_TYPES = new HashMap<>(); + DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection_with_class, null); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); + } + private final DataApiDriverAdapter adapter; public DataApiOpMapper(DataApiDriverAdapter dataApiDriverAdapter) { @@ -47,6 +59,16 @@ public class DataApiOpMapper implements OpMapper { "collection" ); logger.debug(() -> "Using '" + typeAndTarget.enumId + "' op type for op template '" + op.getName() + "'"); + if (DEPRECATED_OP_TYPES.containsKey(typeAndTarget.enumId)) { + DataApiOpType replacement = DEPRECATED_OP_TYPES.get(typeAndTarget.enumId); + if (replacement != null) { + logger.warn(() -> "Op type '" + typeAndTarget.enumId + "' is deprecated; please switch to '" + + replacement + "'. Op template: '" + op.getName() + "'"); + } else { + logger.warn(() -> "Op type '" + typeAndTarget.enumId + "' is discontinued and will be removed" + + " in a future release. Op template: '" + op.getName() + "'"); + } + } return switch (typeAndTarget.enumId) { // LEGACY OPS // admin ops: From 615b3ff3c9ff455fff032c7fd529b21a63bdc944 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 8 Sep 2026 19:04:08 +0200 Subject: [PATCH 16/46] sort op mapper and optype enum, fix filter in legacy f1upd, fix find_distinct by splitting into getLegacyFilterFromOp --- .../adapter/dataapi/DataApiOpMapper.java | 15 +++++-- ...llectionLegacyFindDistinctOpDispenser.java | 2 +- ...tionLegacyFindOneAndUpdateOpDispenser.java | 2 +- .../opdispensers/DataApiOpDispenser.java | 45 ++++++++++++++++++- ...DataApiCollectionLegacyFindDistinctOp.java | 1 + .../adapter/dataapi/ops/DataApiOpType.java | 16 +++++-- 6 files changed, 70 insertions(+), 11 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 5a92fc4df..84de82cce 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -70,7 +70,7 @@ public class DataApiOpMapper implements OpMapper { } } return switch (typeAndTarget.enumId) { - // LEGACY OPS + // TO-DO OPS // admin ops: case create_database -> new DataApiCreateDatabaseOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_databases -> new DataApiListDatabasesOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -82,7 +82,6 @@ public class DataApiOpMapper implements OpMapper { case drop_namespace -> new DataApiDropNamespaceOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-database ops: case create_collection -> new DataApiCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); - case create_collection_with_class -> new DataApiDbLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_collection -> new DataApiDropCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collections -> new DataApiListCollectionsOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collection_names -> @@ -92,13 +91,11 @@ public class DataApiOpMapper implements OpMapper { case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector -> new DataApiCollectionFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector_filter -> new DataApiCollectionFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_by_id -> new DataApiCollectionFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -109,6 +106,16 @@ public class DataApiOpMapper implements OpMapper { case estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); case count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); + + // LEGACY OPS + // admin ops: + // db-admin ops: + // in-database ops: + case create_collection_with_class -> new DataApiDbLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); + // in-collection ops: + case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + // NEW-STYLE OPS case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); }; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java index 952b0e438..c1e8ba263 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java @@ -39,7 +39,7 @@ public class DataApiCollectionLegacyFindDistinctOpDispenser extends DataApiOpDis private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getFilterFromOp(op, l); + Filter filter = getLegacyFilterFromOp(op, l); Class targetClass = getTargetClass(op, l); return new DataApiCollectionLegacyFindDistinctOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java index d49fb79bd..6388b4540 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java @@ -42,7 +42,7 @@ public class DataApiCollectionLegacyFindOneAndUpdateOpDispenser extends DataApiO private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getFilterFromOp(op, l); + Filter filter = getLegacyFilterFromOp(op, l); Update update = getLegacyUpdateFromOp(op, l); CollectionFindOneAndUpdateOptions options = getCollectionLegacyFindOneAndUpdateOptions(op, l); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index a8c0d5517..e459fb67b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -258,7 +258,6 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser getFreeFormFromOp(ParsedOp op, long l, String fieldName, Boolean required) { Optional> ffMapFunc = op.getAsOptionalFunction(fieldName, Map.class); @@ -314,6 +313,50 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> filterFunction = op.getAsOptionalFunction("filters", List.class) + .or(() -> op.getAsOptionalFunction("filter",List.class)); + + if (filterFunction.isPresent()) { + @SuppressWarnings("unchecked") + List> filters = filterFunction.get().apply(l); + List andFilterList = new ArrayList<>(); + List orFilterList = new ArrayList<>(); + for (Map filterFields : filters) { + switch ((String)filterFields.get("conjunction")) { + case "and" -> + addOperatorFilter(andFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); + case "or" -> + addOperatorFilter(orFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); + default -> logger.error(() -> "Conjunction " + filterFields.get("conjunction") + " not supported"); + } + } + if (!andFilterList.isEmpty() && !orFilterList.isEmpty()) { + throw new OpConfigError( + "filters list mixes 'and' and 'or' conjunctions, which is not supported; " + + "use only one conjunction type per filters list" + ); + } + if (!andFilterList.isEmpty()) + filter = Filters.and(andFilterList.toArray(new Filter[0])); + if (!orFilterList.isEmpty()) + filter = Filters.or(orFilterList.toArray(new Filter[0])); + } + return filter; + } + @SuppressWarnings("unchecked") protected CollectionDefinition getLegacyCollectionDefinitionFromOp(ParsedOp op, long l) { CollectionDefinition optionsBldr = new CollectionDefinition(); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java index ed1833586..a602d503d 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindDistinctOp.java @@ -19,6 +19,7 @@ package io.nosqlbench.adapter.dataapi.ops; import com.datastax.astra.client.collections.Collection; import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.core.query.Filters; public class DataApiCollectionLegacyFindDistinctOp extends DataApiBaseOp { private final Collection collection; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index bc6e12f6e..6b07526cc 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -17,7 +17,8 @@ package io.nosqlbench.adapter.dataapi.ops; public enum DataApiOpType { - // LEGACY OPS + + // TO-DO OPS // admin ops: create_database, list_databases, @@ -29,7 +30,6 @@ public enum DataApiOpType { drop_namespace, // in-database ops: create_collection, - create_collection_with_class, delete_collection, list_collections, list_collection_names, @@ -38,13 +38,11 @@ public enum DataApiOpType { insert_one, insert_one_vector, find, - find_distinct, find_one, find_vector, find_vector_filter, find_by_id, update_one, - find_one_and_update, update_many, delete_one, find_one_and_delete, @@ -54,6 +52,16 @@ public enum DataApiOpType { find_one_and_replace, estimated_document_count, count_documents, + + // LEGACY OPS + // admin ops: + // db-admin ops: + // in-database ops: + create_collection_with_class, + // in-collection ops: + find_distinct, + find_one_and_update, + // NEW-STYLE OPS // admin ops: // db-admin ops: From 8a5d394570324d1f28718830ed0c6730abedc935 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 8 Sep 2026 23:11:08 +0200 Subject: [PATCH 17/46] find_one: fix projection, add inclSim, reinstate filters --- .../DataApiCollectionFindOneOpDispenser.java | 10 +++- .../opdispensers/DataApiOpDispenser.java | 46 +++++++++++-------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java index 01dec8766..8cec19716 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java @@ -41,7 +41,7 @@ public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getFilterFromOp(op, l); + Filter filter = getLegacyFilterFromOp(op, l); CollectionFindOneOptions options = getCollectionFindOneOptions(op, l); return new DataApiCollectionFindOneOp( db, @@ -62,7 +62,13 @@ public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { if (projection != null) { options = options.projection(projection); } - options.includeSimilarity(true); + Boolean includeSimilarity = getIncludeSimilarityFromOp(op, l); + if (includeSimilarity != null) { + options.includeSimilarity(includeSimilarity); + } else { + // defaulting to true + options.includeSimilarity(true); + } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index e459fb67b..5b0b23415 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -34,6 +34,7 @@ import io.nosqlbench.adapters.api.templating.ParsedOp; import java.util.*; import java.util.function.LongFunction; +import java.util.stream.Stream; public abstract class DataApiOpDispenser extends BaseOpDispenser { protected final LongFunction targetFunction; @@ -225,28 +226,24 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> projectionFunction = op.getAsOptionalFunction("projection", Map.class); - if (projectionFunction.isPresent()) { - @SuppressWarnings("unchecked") - Map> projectionFields = projectionFunction.get().apply(l); - for (Map.Entry> field : projectionFields.entrySet()) { - List includeFields = field.getValue(); - StringBuffer sb = new StringBuffer(); - for (String includeField : includeFields) { - sb.append(includeField).append(","); - } - sb.deleteCharAt(sb.length() - 1); - if (field.getKey().equalsIgnoreCase("include")) { - projection = Projection.include(sb.toString()); - } else if (field.getKey().equalsIgnoreCase("exclude")) { - projection = Projection.exclude(sb.toString()); - } else { - logger.error("Projection " + field + " not supported"); - } - } + if (projectionFunction.isEmpty()) { + return null; } - return projection; + @SuppressWarnings("unchecked") + Map> projectionFields = projectionFunction.get().apply(l); + return projectionFields.entrySet().stream() + .flatMap(field -> { + String[] arr = field.getValue().toArray(new String[0]); + if (field.getKey().equalsIgnoreCase("include")) { + return Arrays.stream(Projection.include(arr)); + } else if (field.getKey().equalsIgnoreCase("exclude")) { + return Arrays.stream(Projection.exclude(arr)); + } else { + logger.error("Projection directive '" + field.getKey() + "' not supported"); + return Stream.empty(); + } + }).toArray(Projection[]::new); } protected Boolean getUpsertFromOp(ParsedOp op, long l) { @@ -258,6 +255,15 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> includeSimFunction = op.getAsOptionalFunction("include_similarity", Boolean.class); + if (includeSimFunction.isPresent()) { + LongFunction uf = includeSimFunction.get(); + return uf.apply(l); + } + return null; + } + @SuppressWarnings("unchecked") protected Map getFreeFormFromOp(ParsedOp op, long l, String fieldName, Boolean required) { Optional> ffMapFunc = op.getAsOptionalFunction(fieldName, Map.class); From 8722ca69bbda65e8b5f3c6f4bc737efc78ebff19 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 8 Sep 2026 23:41:14 +0200 Subject: [PATCH 18/46] add new-style find_one (only op dispenser differs. freeform filter) --- .../adapter/dataapi/DataApiOpMapper.java | 8 +- .../DataApiCollectionFindOneOpDispenser.java | 2 +- ...ApiCollectionLegacyFindOneOpDispenser.java | 79 +++++++++++++++++++ .../adapter/dataapi/ops/DataApiOpType.java | 3 +- 4 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 84de82cce..87c82ff35 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -37,8 +37,13 @@ public class DataApiOpMapper implements OpMapper { private static final Map DEPRECATED_OP_TYPES; static { DEPRECATED_OP_TYPES = new HashMap<>(); + // admin ops: DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection_with_class, null); + // db-admin ops: + // in-database ops: + // in-collection ops: DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); } @@ -91,7 +96,6 @@ public class DataApiOpMapper implements OpMapper { case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector -> new DataApiCollectionFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector_filter -> new DataApiCollectionFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_by_id -> new DataApiCollectionFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -114,9 +118,11 @@ public class DataApiOpMapper implements OpMapper { case create_collection_with_class -> new DataApiDbLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_one -> new DataApiCollectionLegacyFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); // NEW-STYLE OPS + case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java index 8cec19716..8a0770f89 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java @@ -41,7 +41,7 @@ public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = getFilterFromOp(op, l); CollectionFindOneOptions options = getCollectionFindOneOptions(op, l); return new DataApiCollectionFindOneOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java new file mode 100644 index 000000000..e83861b40 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.collections.commands.options.CollectionFindOneOptions; +import com.datastax.astra.client.core.query.Projection; +import com.datastax.astra.client.core.query.Sort; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOneOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyFindOneOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindOneOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionLegacyFindOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getLegacyFilterFromOp(op, l); + CollectionFindOneOptions options = getCollectionFindOneOptions(op, l); + return new DataApiCollectionFindOneOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + options + ); + }; + } + + private CollectionFindOneOptions getCollectionFindOneOptions(ParsedOp op, long l) { + CollectionFindOneOptions options = new CollectionFindOneOptions(); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + Projection[] projection = getProjectionFromOp(op, l); + if (projection != null) { + options = options.projection(projection); + } + Boolean includeSimilarity = getIncludeSimilarityFromOp(op, l); + if (includeSimilarity != null) { + options.includeSimilarity(includeSimilarity); + } else { + // defaulting to true + options.includeSimilarity(true); + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 6b07526cc..1d365c6c5 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -38,7 +38,6 @@ public enum DataApiOpType { insert_one, insert_one_vector, find, - find_one, find_vector, find_vector_filter, find_by_id, @@ -60,6 +59,7 @@ public enum DataApiOpType { create_collection_with_class, // in-collection ops: find_distinct, + find_one, find_one_and_update, // NEW-STYLE OPS @@ -67,5 +67,6 @@ public enum DataApiOpType { // db-admin ops: // in-database ops: // in-collection ops: + collection_find_one, collection_find_one_and_update, } From 35a846049014d5b2724c3473955b7aefb0426036 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Wed, 9 Sep 2026 23:27:16 +0200 Subject: [PATCH 19/46] just remove commented code --- .../opdispensers/DataApiOpDispenser.java | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 5b0b23415..ff4ffe30c 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -89,39 +89,6 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> filterFunction = op.getAsOptionalFunction("filters", List.class) - .or(() -> op.getAsOptionalFunction("filter",List.class)); - - if (filterFunction.isPresent()) { - @SuppressWarnings("unchecked") - List> filters = filterFunction.get().apply(l); - List andFilterList = new ArrayList<>(); - List orFilterList = new ArrayList<>(); - for (Map filterFields : filters) { - switch ((String)filterFields.get("conjunction")) { - case "and" -> - addOperatorFilter(andFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); - case "or" -> - addOperatorFilter(orFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); - default -> logger.error(() -> "Conjunction " + filterFields.get("conjunction") + " not supported"); - } - } - if (!andFilterList.isEmpty() && !orFilterList.isEmpty()) { - throw new OpConfigError( - "filters list mixes 'and' and 'or' conjunctions, which is not supported; " + - "use only one conjunction type per filters list" - ); - } - if (!andFilterList.isEmpty()) - filter = Filters.and(andFilterList.toArray(new Filter[0])); - if (!orFilterList.isEmpty()) - filter = Filters.or(orFilterList.toArray(new Filter[0])); - } - return filter; - */ } protected void addOperatorFilter(List filtersList, String operator, String fieldName, Object fieldValue) { @@ -159,21 +126,6 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser updateMap = getFreeFormFromOp(op, l, "update", true); return new Update(updateMap); - /* TODO choose whether to switch to freeform for update - Update update = Update.create(); - Optional> updatesFunction = op.getAsOptionalFunction("updates", List.class); - @SuppressWarnings("unchecked") - List> updatesList = updatesFunction - .map(f -> (List>) f.apply(l)) - .orElse(List.of()); - for (Map entry : updatesList) { - String operation = entry.get("operation").toString(); - String field = entry.get("field").toString(); - Object value = entry.get("value"); - applyUpdateOperation(update, operation, field, value); - } - return update; - */ } private void applyUpdateOperation(Update update, String operation, String field, Object value) { From d2633b3deaa3595519fbeab2abefc04249bc0dcb Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 10 Sep 2026 00:06:19 +0200 Subject: [PATCH 20/46] legacy find-based ops, confining to legacy state WIP --- .../dataapi/opdispensers/DataApiCollectionFindOpDispenser.java | 2 +- .../DataApiCollectionFindVectorFilterOpDispenser.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java index 93a57b7ca..b1557c313 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java @@ -42,7 +42,7 @@ public class DataApiCollectionFindOpDispenser extends DataApiOpDispenser { private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getFilterFromOp(op, l); + Filter filter = getLegacyFilterFromOp(op, l); CollectionFindOptions options = getCollectionFindOptions(op, l); return new DataApiCollectionFindOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorFilterOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorFilterOpDispenser.java index 6a3cd1aeb..9f3d14f14 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorFilterOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorFilterOpDispenser.java @@ -39,7 +39,7 @@ public class DataApiCollectionFindVectorFilterOpDispenser extends DataApiOpDispe return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); float[] vector = getVectorValues(op, l); - Filter filter = getFilterFromOp(op, l); + Filter filter = getLegacyFilterFromOp(op, l); int limit = getLimit(op, l); return new DataApiCollectionFindVectorFilterOp( db, From 3c317a4dbbd4cacbe131e8cc47a6efdbd1865abb Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 10 Sep 2026 00:21:55 +0200 Subject: [PATCH 21/46] legacy find-based ops, confining to legacy state --- .../adapter/dataapi/DataApiOpMapper.java | 8 ++++---- ...iCollectionLegacyFindByIdOpDispenser.java} | 14 ++++++------- ...taApiCollectionLegacyFindOpDispenser.java} | 14 ++++++------- ...ionLegacyFindVectorFilterOpDispenser.java} | 20 ++++++++++--------- ...ollectionLegacyFindVectorOpDispenser.java} | 20 +++++++++---------- ...=> DataApiCollectionLegacyFindByIdOp.java} | 4 ++-- ...ava => DataApiCollectionLegacyFindOp.java} | 4 ++-- ...piCollectionLegacyFindVectorFilterOp.java} | 4 ++-- ... DataApiCollectionLegacyFindVectorOp.java} | 4 ++-- .../adapter/dataapi/ops/DataApiOpType.java | 8 ++++---- 10 files changed, 50 insertions(+), 50 deletions(-) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionFindByIdOpDispenser.java => DataApiCollectionLegacyFindByIdOpDispenser.java} (77%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionFindOpDispenser.java => DataApiCollectionLegacyFindOpDispenser.java} (85%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionFindVectorOpDispenser.java => DataApiCollectionLegacyFindVectorFilterOpDispenser.java} (68%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionFindVectorFilterOpDispenser.java => DataApiCollectionLegacyFindVectorOpDispenser.java} (75%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionFindByIdOp.java => DataApiCollectionLegacyFindByIdOp.java} (86%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionFindOp.java => DataApiCollectionLegacyFindOp.java} (88%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionFindVectorFilterOp.java => DataApiCollectionLegacyFindVectorFilterOp.java} (88%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionFindVectorOp.java => DataApiCollectionLegacyFindVectorOp.java} (88%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 87c82ff35..e45e4c768 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -95,10 +95,6 @@ public class DataApiOpMapper implements OpMapper { case insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_vector -> new DataApiCollectionFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_vector_filter -> new DataApiCollectionFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_by_id -> new DataApiCollectionFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -117,6 +113,10 @@ public class DataApiOpMapper implements OpMapper { // in-database ops: case create_collection_with_class -> new DataApiDbLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: + case find -> new DataApiCollectionLegacyFindOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_vector -> new DataApiCollectionLegacyFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_vector_filter -> new DataApiCollectionLegacyFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_by_id -> new DataApiCollectionLegacyFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one -> new DataApiCollectionLegacyFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindByIdOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindByIdOpDispenser.java similarity index 77% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindByIdOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindByIdOpDispenser.java index 58382780e..92e9262cc 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindByIdOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindByIdOpDispenser.java @@ -22,7 +22,7 @@ import com.datastax.astra.client.core.query.Projection; import com.datastax.astra.client.core.query.Sort; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindByIdOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyFindByIdOp; import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOneOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; @@ -30,19 +30,19 @@ import org.apache.logging.log4j.Logger; import java.util.function.LongFunction; -public class DataApiCollectionFindByIdOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionFindByIdOpDispenser.class); - private final LongFunction opFunction; - public DataApiCollectionFindByIdOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { +public class DataApiCollectionLegacyFindByIdOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindByIdOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionLegacyFindByIdOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); Object id = getIdFromOp(op, l); - return new DataApiCollectionFindByIdOp( + return new DataApiCollectionLegacyFindByIdOp( db, db.getCollection(targetFunction.apply(l)), id diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java similarity index 85% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java index b1557c313..99ad2a87f 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java @@ -23,7 +23,7 @@ import com.datastax.astra.client.core.query.Projection; import com.datastax.astra.client.core.query.Sort; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyFindOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -31,20 +31,20 @@ import org.apache.logging.log4j.Logger; import java.util.Optional; import java.util.function.LongFunction; -public class DataApiCollectionFindOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionFindOpDispenser.class); - private final LongFunction opFunction; - public DataApiCollectionFindOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { +public class DataApiCollectionLegacyFindOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionLegacyFindOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getLegacyFilterFromOp(op, l); CollectionFindOptions options = getCollectionFindOptions(op, l); - return new DataApiCollectionFindOp( + return new DataApiCollectionLegacyFindOp( db, db.getCollection(targetFunction.apply(l)), filter, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorFilterOpDispenser.java similarity index 68% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorFilterOpDispenser.java index 04bf31fd7..e6cad50df 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorFilterOpDispenser.java @@ -17,34 +17,36 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import com.datastax.astra.client.databases.Database; -import com.datastax.astra.client.core.query.Sort; +import com.datastax.astra.client.core.query.Filter; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindVectorOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyFindVectorFilterOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.function.LongFunction; -public class DataApiCollectionFindVectorOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionFindVectorOpDispenser.class); - private final LongFunction opFunction; - public DataApiCollectionFindVectorOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { +public class DataApiCollectionLegacyFindVectorFilterOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindVectorFilterOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionLegacyFindVectorFilterOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); float[] vector = getVectorValues(op, l); + Filter filter = getLegacyFilterFromOp(op, l); int limit = getLimit(op, l); - return new DataApiCollectionFindVectorOp( + return new DataApiCollectionLegacyFindVectorFilterOp( db, db.getCollection(targetFunction.apply(l)), vector, - limit + limit, + filter ); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorFilterOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorOpDispenser.java similarity index 75% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorFilterOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorOpDispenser.java index 9f3d14f14..c74151b01 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindVectorFilterOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorOpDispenser.java @@ -17,36 +17,34 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import com.datastax.astra.client.databases.Database; -import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.core.query.Sort; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindVectorFilterOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyFindVectorOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.function.LongFunction; -public class DataApiCollectionFindVectorFilterOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionFindVectorFilterOpDispenser.class); - private final LongFunction opFunction; - public DataApiCollectionFindVectorFilterOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { +public class DataApiCollectionLegacyFindVectorOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindVectorOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionLegacyFindVectorOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); float[] vector = getVectorValues(op, l); - Filter filter = getLegacyFilterFromOp(op, l); int limit = getLimit(op, l); - return new DataApiCollectionFindVectorFilterOp( + return new DataApiCollectionLegacyFindVectorOp( db, db.getCollection(targetFunction.apply(l)), vector, - limit, - filter + limit ); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindByIdOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindByIdOp.java similarity index 86% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindByIdOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindByIdOp.java index 4161f539d..efb85e527 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindByIdOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindByIdOp.java @@ -19,11 +19,11 @@ package io.nosqlbench.adapter.dataapi.ops; import com.datastax.astra.client.collections.Collection; import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.collections.definition.documents.Document; -public class DataApiCollectionFindByIdOp extends DataApiBaseOp { +public class DataApiCollectionLegacyFindByIdOp extends DataApiBaseOp { private final Collection collection; private final Object id; - public DataApiCollectionFindByIdOp(Database db, Collection collection, Object id) { + public DataApiCollectionLegacyFindByIdOp(Database db, Collection collection, Object id) { super(db); this.collection = collection; this.id = id; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOp.java similarity index 88% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOp.java index 940c70609..edf946934 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOp.java @@ -25,12 +25,12 @@ import com.datastax.astra.client.collections.commands.cursor.CollectionFindCurso import java.util.List; -public class DataApiCollectionFindOp extends DataApiBaseOp { +public class DataApiCollectionLegacyFindOp extends DataApiBaseOp { private final Collection collection; private final Filter filter; private final CollectionFindOptions options; - public DataApiCollectionFindOp(Database db, Collection collection, Filter filter, CollectionFindOptions options) { + public DataApiCollectionLegacyFindOp(Database db, Collection collection, Filter filter, CollectionFindOptions options) { super(db); this.collection = collection; this.filter = filter; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindVectorFilterOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindVectorFilterOp.java similarity index 88% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindVectorFilterOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindVectorFilterOp.java index 38b4c629d..58d6527a9 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindVectorFilterOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindVectorFilterOp.java @@ -24,12 +24,12 @@ import com.datastax.astra.client.collections.definition.documents.Document; import com.datastax.astra.client.core.query.Filter; import com.datastax.astra.client.core.query.Sort; -public class DataApiCollectionFindVectorFilterOp extends DataApiBaseOp { +public class DataApiCollectionLegacyFindVectorFilterOp extends DataApiBaseOp { private final Collection collection; private final Filter filter; private final CollectionFindOptions options; - public DataApiCollectionFindVectorFilterOp(Database db, Collection collection, float[] vector, int limit, Filter filter) { + public DataApiCollectionLegacyFindVectorFilterOp(Database db, Collection collection, float[] vector, int limit, Filter filter) { super(db); this.collection = collection; this.filter = filter; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindVectorOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindVectorOp.java similarity index 88% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindVectorOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindVectorOp.java index 7d1536644..7dc43b3d6 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindVectorOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindVectorOp.java @@ -23,11 +23,11 @@ import com.datastax.astra.client.core.query.Sort; import com.datastax.astra.client.collections.commands.cursor.CollectionFindCursor; import com.datastax.astra.client.collections.commands.options.CollectionFindOptions; -public class DataApiCollectionFindVectorOp extends DataApiBaseOp { +public class DataApiCollectionLegacyFindVectorOp extends DataApiBaseOp { private final Collection collection; private final CollectionFindOptions options; - public DataApiCollectionFindVectorOp(Database db, Collection collection, float[] vector, int limit) { + public DataApiCollectionLegacyFindVectorOp(Database db, Collection collection, float[] vector, int limit) { super(db); this.collection = collection; this.options = new CollectionFindOptions().sort(Sort.vector(vector)).limit(limit); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 1d365c6c5..f1e23e1e3 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -37,10 +37,6 @@ public enum DataApiOpType { insert_many, insert_one, insert_one_vector, - find, - find_vector, - find_vector_filter, - find_by_id, update_one, update_many, delete_one, @@ -58,6 +54,10 @@ public enum DataApiOpType { // in-database ops: create_collection_with_class, // in-collection ops: + find, + find_vector, + find_vector_filter, + find_by_id, find_distinct, find_one, find_one_and_update, From 66f628905cc739e6f80098306198b7ee7eba1956 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 10 Sep 2026 06:43:16 +0200 Subject: [PATCH 22/46] deprecate legacy finds; introduce new find to replace them --- .../adapter/dataapi/DataApiOpMapper.java | 5 ++ .../DataApiCollectionFindOneOpDispenser.java | 10 +-- .../DataApiCollectionFindOpDispenser.java | 85 +++++++++++++++++++ ...ApiCollectionLegacyFindOneOpDispenser.java | 9 +- ...ataApiCollectionLegacyFindOpDispenser.java | 8 +- .../opdispensers/DataApiOpDispenser.java | 24 +++++- ...ndOp.java => DataApiCollectionFindOp.java} | 4 +- .../adapter/dataapi/ops/DataApiOpType.java | 1 + 8 files changed, 127 insertions(+), 19 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionLegacyFindOp.java => DataApiCollectionFindOp.java} (88%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index e45e4c768..fd0f7c22d 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -42,6 +42,10 @@ public class DataApiOpMapper implements OpMapper { // db-admin ops: // in-database ops: // in-collection ops: + DEPRECATED_OP_TYPES.put(DataApiOpType.find, DataApiOpType.collection_find); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector, DataApiOpType.collection_find); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector_filter, DataApiOpType.collection_find); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_by_id, null); DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); @@ -122,6 +126,7 @@ public class DataApiOpMapper implements OpMapper { case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); // NEW-STYLE OPS + case collection_find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); }; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java index 8a0770f89..6af0190cd 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java @@ -28,6 +28,7 @@ import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.Optional; import java.util.function.LongFunction; public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { @@ -62,12 +63,9 @@ public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { if (projection != null) { options = options.projection(projection); } - Boolean includeSimilarity = getIncludeSimilarityFromOp(op, l); - if (includeSimilarity != null) { - options.includeSimilarity(includeSimilarity); - } else { - // defaulting to true - options.includeSimilarity(true); + Optional includeSimilarity = getIncludeSimilarityFromOp(op, l); + if (includeSimilarity.isPresent()) { + options.includeSimilarity(includeSimilarity.get()); } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java new file mode 100644 index 000000000..f3429c86f --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.collections.commands.options.CollectionFindOptions; +import com.datastax.astra.client.core.query.Projection; +import com.datastax.astra.client.core.query.Sort; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Optional; +import java.util.function.LongFunction; + +public class DataApiCollectionFindOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionFindOpDispenser.class); + private final LongFunction opFunction; + public DataApiCollectionFindOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getFilterFromOp(op, l); + CollectionFindOptions options = getCollectionFindOptions(op, l); + return new DataApiCollectionFindOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + options + ); + }; + } + + private CollectionFindOptions getCollectionFindOptions(ParsedOp op, long l) { + CollectionFindOptions options = new CollectionFindOptions(); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + Projection[] projection = getProjectionFromOp(op, l); + if (projection != null) { + options = options.projection(projection); + } + Optional limit = getLimitFromOp(op, l); + if (limit.isPresent()) { + options = options.limit(limit.get()); + } + Optional skip = getSkipFromOp(op, l); + if (skip.isPresent()) { + options = options.skip(skip.get()); + } + Optional includeSimilarity = getIncludeSimilarityFromOp(op, l); + if (includeSimilarity.isPresent()) { + options.includeSimilarity(includeSimilarity.get()); + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java index e83861b40..ff881a81d 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java @@ -28,6 +28,7 @@ import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.Optional; import java.util.function.LongFunction; public class DataApiCollectionLegacyFindOneOpDispenser extends DataApiOpDispenser { @@ -62,11 +63,11 @@ public class DataApiCollectionLegacyFindOneOpDispenser extends DataApiOpDispense if (projection != null) { options = options.projection(projection); } - Boolean includeSimilarity = getIncludeSimilarityFromOp(op, l); - if (includeSimilarity != null) { - options.includeSimilarity(includeSimilarity); + Optional includeSimilarity = getIncludeSimilarityFromOp(op, l); + if (includeSimilarity.isPresent()) { + options.includeSimilarity(includeSimilarity.get()); } else { - // defaulting to true + // defaulting to true (backward-compatibility) options.includeSimilarity(true); } return options; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java index 99ad2a87f..e617dc69f 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java @@ -23,7 +23,7 @@ import com.datastax.astra.client.core.query.Projection; import com.datastax.astra.client.core.query.Sort; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyFindOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -33,18 +33,18 @@ import java.util.function.LongFunction; public class DataApiCollectionLegacyFindOpDispenser extends DataApiOpDispenser { private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindOpDispenser.class); - private final LongFunction opFunction; + private final LongFunction opFunction; public DataApiCollectionLegacyFindOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getLegacyFilterFromOp(op, l); CollectionFindOptions options = getCollectionFindOptions(op, l); - return new DataApiCollectionLegacyFindOp( + return new DataApiCollectionFindOp( db, db.getCollection(targetFunction.apply(l)), filter, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index ff4ffe30c..06016411e 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -207,13 +207,31 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser getIncludeSimilarityFromOp(ParsedOp op, long l) { Optional> includeSimFunction = op.getAsOptionalFunction("include_similarity", Boolean.class); if (includeSimFunction.isPresent()) { LongFunction uf = includeSimFunction.get(); - return uf.apply(l); + return Optional.of(uf.apply(l)); } - return null; + return Optional.empty(); + } + + protected Optional getLimitFromOp(ParsedOp op, long l) { + Optional> limitFunction = op.getAsOptionalFunction("limit", Integer.class); + if (limitFunction.isPresent()) { + LongFunction lf = limitFunction.get(); + return Optional.of(lf.apply(l)); + } + return Optional.empty(); + } + + protected Optional getSkipFromOp(ParsedOp op, long l) { + Optional> skipFunction = op.getAsOptionalFunction("skip", Integer.class); + if (skipFunction.isPresent()) { + LongFunction sf = skipFunction.get(); + return Optional.of(sf.apply(l)); + } + return Optional.empty(); } @SuppressWarnings("unchecked") diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOp.java similarity index 88% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOp.java index edf946934..940c70609 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyFindOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindOp.java @@ -25,12 +25,12 @@ import com.datastax.astra.client.collections.commands.cursor.CollectionFindCurso import java.util.List; -public class DataApiCollectionLegacyFindOp extends DataApiBaseOp { +public class DataApiCollectionFindOp extends DataApiBaseOp { private final Collection collection; private final Filter filter; private final CollectionFindOptions options; - public DataApiCollectionLegacyFindOp(Database db, Collection collection, Filter filter, CollectionFindOptions options) { + public DataApiCollectionFindOp(Database db, Collection collection, Filter filter, CollectionFindOptions options) { super(db); this.collection = collection; this.filter = filter; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index f1e23e1e3..fc70df8ad 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -67,6 +67,7 @@ public enum DataApiOpType { // db-admin ops: // in-database ops: // in-collection ops: + collection_find, collection_find_one, collection_find_one_and_update, } From e0a0458d46dbdaac217d49687fd0cef4acf98887 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 10 Sep 2026 09:44:49 +0200 Subject: [PATCH 23/46] fix wrong allow/deny-indexing representation in create_collection_with_class --- .../adapter/dataapi/DataApiOpMapper.java | 2 +- ...egacyCreateCollectionWithClassOpDispenser.java} | 14 +++++++------- .../dataapi/opdispensers/DataApiOpDispenser.java | 14 ++++++++------ ... DataApiLegacyCreateCollectionWithClassOp.java} | 4 ++-- 4 files changed, 18 insertions(+), 16 deletions(-) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiDbLegacyCreateCollectionWithClassOpDispenser.java => DataApiLegacyCreateCollectionWithClassOpDispenser.java} (73%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiDbLegacyCreateCollectionWithClassOp.java => DataApiLegacyCreateCollectionWithClassOp.java} (84%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index fd0f7c22d..172e859e8 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -115,7 +115,7 @@ public class DataApiOpMapper implements OpMapper { // admin ops: // db-admin ops: // in-database ops: - case create_collection_with_class -> new DataApiDbLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); + case create_collection_with_class -> new DataApiLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case find -> new DataApiCollectionLegacyFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector -> new DataApiCollectionLegacyFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbLegacyCreateCollectionWithClassOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionWithClassOpDispenser.java similarity index 73% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbLegacyCreateCollectionWithClassOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionWithClassOpDispenser.java index bf9cfaca2..1d7f2289a 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbLegacyCreateCollectionWithClassOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionWithClassOpDispenser.java @@ -18,24 +18,24 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiDbLegacyCreateCollectionWithClassOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiLegacyCreateCollectionWithClassOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.function.LongFunction; -public class DataApiDbLegacyCreateCollectionWithClassOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiDbLegacyCreateCollectionWithClassOpDispenser.class); - private final LongFunction opFunction; +public class DataApiLegacyCreateCollectionWithClassOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiLegacyCreateCollectionWithClassOpDispenser.class); + private final LongFunction opFunction; - public DataApiDbLegacyCreateCollectionWithClassOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + public DataApiLegacyCreateCollectionWithClassOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { - return (l) -> new DataApiDbLegacyCreateCollectionWithClassOp( + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> new DataApiLegacyCreateCollectionWithClassOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), this.getLegacyCollectionDefinitionFromOp(op, l), diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 06016411e..7cc4fe467 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -368,15 +368,17 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> allowFunc = op.getAsOptionalFunction("allowIndex", List.class); + @SuppressWarnings("unchecked") + Optional>> allowFunc = (Optional>>) (Optional) op.getAsOptionalFunction("allowIndex", List.class); if (allowFunc.isPresent()) { - LongFunction af = allowFunc.get(); - optionsBldr = optionsBldr.indexingAllow(Arrays.toString(af.apply(l).toArray(new String[0]))); + LongFunction> af = allowFunc.get(); + optionsBldr = optionsBldr.indexingAllow(af.apply(l).toArray(new String[0])); } - Optional> denyFunc = op.getAsOptionalFunction("denyIndex", List.class); + @SuppressWarnings("unchecked") + Optional>> denyFunc = (Optional>>) (Optional) op.getAsOptionalFunction("denyIndex", List.class); if (denyFunc.isPresent()) { - LongFunction df = denyFunc.get(); - optionsBldr = optionsBldr.indexingDeny(Arrays.toString(df.apply(l).toArray(new String[0]))); + LongFunction> df = denyFunc.get(); + optionsBldr = optionsBldr.indexingDeny(df.apply(l).toArray(new String[0])); } return optionsBldr; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbLegacyCreateCollectionWithClassOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyCreateCollectionWithClassOp.java similarity index 84% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbLegacyCreateCollectionWithClassOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyCreateCollectionWithClassOp.java index 27ddae619..b74e21785 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbLegacyCreateCollectionWithClassOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyCreateCollectionWithClassOp.java @@ -19,12 +19,12 @@ package io.nosqlbench.adapter.dataapi.ops; import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.collections.definition.CollectionDefinition; -public class DataApiDbLegacyCreateCollectionWithClassOp extends DataApiBaseOp { +public class DataApiLegacyCreateCollectionWithClassOp extends DataApiBaseOp { private final String collectionName; private final CollectionDefinition definition; private final Class clazz; - public DataApiDbLegacyCreateCollectionWithClassOp(Database db, String collectionName, CollectionDefinition definition, Class clazz) { + public DataApiLegacyCreateCollectionWithClassOp(Database db, String collectionName, CollectionDefinition definition, Class clazz) { super(db); this.collectionName = collectionName; this.definition = definition; From 7019fe9e7e115da183ce87f046b86886d011fd8c Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 10 Sep 2026 10:37:53 +0200 Subject: [PATCH 24/46] deleteOne and deleteMany: moved old ops to legacy, created new ops, added deprecation - completed --- .../adapter/dataapi/DataApiOpMapper.java | 13 ++-- ...CollectionLegacyDeleteAllOpDispenser.java} | 14 ++-- ...CollectionLegacyDeleteManyOpDispenser.java | 56 +++++++++++++++ ...iCollectionLegacyDeleteOneOpDispenser.java | 69 +++++++++++++++++++ ...> DataApiCollectionLegacyDeleteAllOp.java} | 4 +- .../adapter/dataapi/ops/DataApiOpType.java | 8 ++- 6 files changed, 148 insertions(+), 16 deletions(-) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionDeleteAllOpDispenser.java => DataApiCollectionLegacyDeleteAllOpDispenser.java} (71%) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionDeleteAllOp.java => DataApiCollectionLegacyDeleteAllOp.java} (85%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 172e859e8..05858c212 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -38,10 +38,13 @@ public class DataApiOpMapper implements OpMapper { static { DEPRECATED_OP_TYPES = new HashMap<>(); // admin ops: - DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection_with_class, null); + DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection_with_class, null); // TODO => newstyle create coll. // db-admin ops: // in-database ops: // in-collection ops: + DEPRECATED_OP_TYPES.put(DataApiOpType.delete_all, DataApiOpType.collection_delete_many); + DEPRECATED_OP_TYPES.put(DataApiOpType.delete_many, DataApiOpType.collection_delete_many); + DEPRECATED_OP_TYPES.put(DataApiOpType.delete_one, DataApiOpType.collection_delete_one); DEPRECATED_OP_TYPES.put(DataApiOpType.find, DataApiOpType.collection_find); DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector, DataApiOpType.collection_find); DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector_filter, DataApiOpType.collection_find); @@ -101,10 +104,7 @@ public class DataApiOpMapper implements OpMapper { case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); - case delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); - case delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); - case delete_all -> new DataApiCollectionDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); case estimated_document_count -> @@ -117,6 +117,11 @@ public class DataApiOpMapper implements OpMapper { // in-database ops: case create_collection_with_class -> new DataApiLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: + case collection_delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case delete_one -> new DataApiCollectionLegacyDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case delete_many -> new DataApiCollectionLegacyDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); + case delete_all -> new DataApiCollectionLegacyDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); case find -> new DataApiCollectionLegacyFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector -> new DataApiCollectionLegacyFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector_filter -> new DataApiCollectionLegacyFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteAllOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteAllOpDispenser.java similarity index 71% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteAllOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteAllOpDispenser.java index 569a0685e..721ef5281 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteAllOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteAllOpDispenser.java @@ -19,27 +19,27 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import com.datastax.astra.client.databases.Database; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionDeleteAllOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyDeleteAllOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.function.LongFunction; -public class DataApiCollectionDeleteAllOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionDeleteAllOpDispenser.class); - private final LongFunction opFunction; +public class DataApiCollectionLegacyDeleteAllOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyDeleteAllOpDispenser.class); + private final LongFunction opFunction; - public DataApiCollectionDeleteAllOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + public DataApiCollectionLegacyDeleteAllOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - return new DataApiCollectionDeleteAllOp( + return new DataApiCollectionLegacyDeleteAllOp( db, db.getCollection(targetFunction.apply(l)) ); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java new file mode 100644 index 000000000..c3ec617b9 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionDeleteManyOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyDeleteManyOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyDeleteManyOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionLegacyDeleteManyOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getLegacyFilterFromOp(op, l); + + return new DataApiCollectionDeleteManyOp( + db, + db.getCollection(targetFunction.apply(l)), + filter + ); + }; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java new file mode 100644 index 000000000..9356b23ee --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.collections.commands.options.CollectionDeleteOneOptions; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.core.query.Sort; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionDeleteOneOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyDeleteOneOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyDeleteOneOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionLegacyDeleteOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getLegacyFilterFromOp(op, l); + CollectionDeleteOneOptions options = getCollectionDeleteOneOptions(op, l); + + return new DataApiCollectionDeleteOneOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + options + ); + }; + } + + private CollectionDeleteOneOptions getCollectionDeleteOneOptions(ParsedOp op, long l) { + CollectionDeleteOneOptions options = new CollectionDeleteOneOptions(); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionDeleteAllOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyDeleteAllOp.java similarity index 85% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionDeleteAllOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyDeleteAllOp.java index dbe5fa1c5..2f1538699 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionDeleteAllOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyDeleteAllOp.java @@ -19,10 +19,10 @@ package io.nosqlbench.adapter.dataapi.ops; import com.datastax.astra.client.collections.Collection; import com.datastax.astra.client.databases.Database; -public class DataApiCollectionDeleteAllOp extends DataApiBaseOp { +public class DataApiCollectionLegacyDeleteAllOp extends DataApiBaseOp { private final Collection collection; - public DataApiCollectionDeleteAllOp(Database db, Collection collection) { + public DataApiCollectionLegacyDeleteAllOp(Database db, Collection collection) { super(db); this.collection = collection; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index fc70df8ad..f6e71506b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -39,10 +39,7 @@ public enum DataApiOpType { insert_one_vector, update_one, update_many, - delete_one, find_one_and_delete, - delete_many, - delete_all, replace_one, find_one_and_replace, estimated_document_count, @@ -54,6 +51,9 @@ public enum DataApiOpType { // in-database ops: create_collection_with_class, // in-collection ops: + delete_one, + delete_many, + delete_all, find, find_vector, find_vector_filter, @@ -67,6 +67,8 @@ public enum DataApiOpType { // db-admin ops: // in-database ops: // in-collection ops: + collection_delete_many, + collection_delete_one, collection_find, collection_find_one, collection_find_one_and_update, From 459ab94d4ab69ea328813b0702bfa50dfb73b324 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:38:26 +0200 Subject: [PATCH 25/46] estimatedDocumentCount (no in-dispenser changes needed) --- .../io/nosqlbench/adapter/dataapi/DataApiOpMapper.java | 7 +++++-- .../io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 05858c212..f5d294566 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -52,6 +52,7 @@ public class DataApiOpMapper implements OpMapper { DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); + DEPRECATED_OP_TYPES.put(DataApiOpType.estimated_document_count, DataApiOpType.collection_estimated_document_count); } private final DataApiDriverAdapter adapter; @@ -107,8 +108,6 @@ public class DataApiOpMapper implements OpMapper { case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); - case estimated_document_count -> - new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); case count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); // LEGACY OPS @@ -129,11 +128,15 @@ public class DataApiOpMapper implements OpMapper { case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one -> new DataApiCollectionLegacyFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + case estimated_document_count -> + new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); // NEW-STYLE OPS case collection_find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_estimated_document_count -> + new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index f6e71506b..26210ad98 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -42,9 +42,8 @@ public enum DataApiOpType { find_one_and_delete, replace_one, find_one_and_replace, - estimated_document_count, count_documents, - + // LEGACY OPS // admin ops: // db-admin ops: @@ -61,6 +60,7 @@ public enum DataApiOpType { find_distinct, find_one, find_one_and_update, + estimated_document_count, // NEW-STYLE OPS // admin ops: @@ -72,4 +72,5 @@ public enum DataApiOpType { collection_find, collection_find_one, collection_find_one_and_update, + collection_estimated_document_count, } From 5b438f53565573b0d5b1dced2712dbf5a34b445f Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:22:11 +0200 Subject: [PATCH 26/46] countDocuments, add new op and split from legacy --- .../adapter/dataapi/DataApiOpMapper.java | 8 ++- ...piCollectionCountDocumentsOpDispenser.java | 9 ++- ...ectionLegacyCountDocumentsOpDispenser.java | 58 +++++++++++++++++++ .../DataApiCollectionCountDocumentsOp.java | 24 ++++++-- ...taApiCollectionLegacyCountDocumentsOp.java | 45 ++++++++++++++ .../adapter/dataapi/ops/DataApiOpType.java | 3 +- 6 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyCountDocumentsOp.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index f5d294566..4e8e905cd 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -108,7 +108,6 @@ public class DataApiOpMapper implements OpMapper { case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); - case count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); // LEGACY OPS // admin ops: @@ -116,8 +115,6 @@ public class DataApiOpMapper implements OpMapper { // in-database ops: case create_collection_with_class -> new DataApiLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: - case collection_delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); - case collection_delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_one -> new DataApiCollectionLegacyDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_many -> new DataApiCollectionLegacyDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_all -> new DataApiCollectionLegacyDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -128,15 +125,20 @@ public class DataApiOpMapper implements OpMapper { case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one -> new DataApiCollectionLegacyFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + case count_documents -> new DataApiCollectionLegacyCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); case estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); // NEW-STYLE OPS + // in-collection ops: case collection_find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionCountDocumentsOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionCountDocumentsOpDispenser.java index 63cf997e6..2398817d7 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionCountDocumentsOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionCountDocumentsOpDispenser.java @@ -26,6 +26,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.function.LongFunction; +import java.util.Optional; public class DataApiCollectionCountDocumentsOpDispenser extends DataApiOpDispenser { private static final Logger logger = LogManager.getLogger(DataApiCollectionCountDocumentsOpDispenser.class); @@ -40,7 +41,13 @@ public class DataApiCollectionCountDocumentsOpDispenser extends DataApiOpDispens return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getFilterFromOp(op, l); - int upperBound = op.getAsRequiredFunction("upperbound", Integer.class).apply(l); + Optional> ubf = op.getAsOptionalFunction("upper_bound", Integer.class); + Optional upperBound; + if (ubf.isPresent()) { + upperBound = Optional.of(ubf.get().apply(l)); + } else { + upperBound = Optional.empty(); + } return new DataApiCollectionCountDocumentsOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java new file mode 100644 index 000000000..fa4a99c45 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyCountDocumentsOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyCountDocumentsOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyCountDocumentsOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionLegacyCountDocumentsOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getLegacyFilterFromOp(op, l); + int upperBound = op.getAsRequiredFunction("upperbound", Integer.class).apply(l); + + return new DataApiCollectionLegacyCountDocumentsOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + upperBound + ); + }; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionCountDocumentsOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionCountDocumentsOp.java index a7d7d416f..1977fb948 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionCountDocumentsOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionCountDocumentsOp.java @@ -22,12 +22,17 @@ import com.datastax.astra.client.collections.exceptions.TooManyDocumentsToCountE import com.datastax.astra.client.collections.definition.documents.Document; import com.datastax.astra.client.core.query.Filter; +import java.util.Optional; + public class DataApiCollectionCountDocumentsOp extends DataApiBaseOp { private final Collection collection; private final Filter filter; - private final int upperBound; + private final Optional upperBound; - public DataApiCollectionCountDocumentsOp(Database db, Collection collection, Filter filter, int upperBound) { + private final int MAX_UPPER_BOUND = 1000; + private final int SILENT_FAILED_COUNT_RESULT = -1; + + public DataApiCollectionCountDocumentsOp(Database db, Collection collection, Filter filter, Optional upperBound) { super(db); this.collection = collection; this.filter = filter; @@ -36,10 +41,21 @@ public class DataApiCollectionCountDocumentsOp extends DataApiBaseOp { @Override public Object apply(long value) { + // upper-bound being optional enables a pattern that ignores the "moreData" + // (getting rid of the 'upper bound' client-only feature). Still honored if passed (incl. throwing the error). + int upperBoundToUse = MAX_UPPER_BOUND; + boolean shouldThrowBoundExceeded = false; + if (upperBound.isPresent()) { + upperBoundToUse = upperBound.get(); + shouldThrowBoundExceeded = true; + } try { - return collection.countDocuments(filter, upperBound); + return collection.countDocuments(filter, upperBoundToUse); } catch (TooManyDocumentsToCountException e) { - throw new RuntimeException(e); + if (shouldThrowBoundExceeded) { + throw new RuntimeException(e); + } + return SILENT_FAILED_COUNT_RESULT; } } } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyCountDocumentsOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyCountDocumentsOp.java new file mode 100644 index 000000000..1088fdd0e --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyCountDocumentsOp.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.ops; + +import com.datastax.astra.client.collections.Collection; +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.collections.exceptions.TooManyDocumentsToCountException; +import com.datastax.astra.client.collections.definition.documents.Document; +import com.datastax.astra.client.core.query.Filter; + +public class DataApiCollectionLegacyCountDocumentsOp extends DataApiBaseOp { + private final Collection collection; + private final Filter filter; + private final int upperBound; + + public DataApiCollectionLegacyCountDocumentsOp(Database db, Collection collection, Filter filter, int upperBound) { + super(db); + this.collection = collection; + this.filter = filter; + this.upperBound = upperBound; + } + + @Override + public Object apply(long value) { + try { + return collection.countDocuments(filter, upperBound); + } catch (TooManyDocumentsToCountException e) { + throw new RuntimeException(e); + } + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 26210ad98..e0ae1558e 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -42,7 +42,6 @@ public enum DataApiOpType { find_one_and_delete, replace_one, find_one_and_replace, - count_documents, // LEGACY OPS // admin ops: @@ -61,6 +60,7 @@ public enum DataApiOpType { find_one, find_one_and_update, estimated_document_count, + count_documents, // NEW-STYLE OPS // admin ops: @@ -73,4 +73,5 @@ public enum DataApiOpType { collection_find_one, collection_find_one_and_update, collection_estimated_document_count, + collection_count_documents, } From cfbf9393ee1944c908237fec8378806a9e15c6fe Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:36:53 +0200 Subject: [PATCH 27/46] update1 fully made legacy --- .../io/nosqlbench/adapter/dataapi/DataApiOpMapper.java | 2 +- ...a => DataApiCollectionLegacyUpdateOneOpDispenser.java} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionUpdateOneOpDispenser.java => DataApiCollectionLegacyUpdateOneOpDispenser.java} (89%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 4e8e905cd..95582cf2b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -103,7 +103,7 @@ public class DataApiOpMapper implements OpMapper { case insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); - case update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case update_one -> new DataApiCollectionLegacyUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java similarity index 89% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java index d5748e909..dc9fdbf3c 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java @@ -32,11 +32,11 @@ import java.util.Map; import java.util.Optional; import java.util.function.LongFunction; -public class DataApiCollectionUpdateOneOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionUpdateOneOpDispenser.class); +public class DataApiCollectionLegacyUpdateOneOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyUpdateOneOpDispenser.class); private final LongFunction opFunction; - public DataApiCollectionUpdateOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + public DataApiCollectionLegacyUpdateOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } @@ -44,7 +44,7 @@ public class DataApiCollectionUpdateOneOpDispenser extends DataApiOpDispenser { private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getFilterFromOp(op, l); + Filter filter = getLegacyFilterFromOp(op, l); CollectionUpdateOneOptions options = getCollectionUpdateOneOptions(op, l); LongFunction docMapFunc = op.getAsRequiredFunction("update", Map.class); From abbd60060b2d9799b75326c168292fbaf0d45bd4 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:47:33 +0200 Subject: [PATCH 28/46] new-style updateOne added --- .../adapter/dataapi/DataApiOpMapper.java | 4 +- ...DataApiCollectionUpdateOneOpDispenser.java | 78 +++++++++++++++++++ .../adapter/dataapi/ops/DataApiOpType.java | 3 +- 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 95582cf2b..6a1ba47d5 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -51,6 +51,7 @@ public class DataApiOpMapper implements OpMapper { DEPRECATED_OP_TYPES.put(DataApiOpType.find_by_id, null); DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.update_one, DataApiOpType.collection_update_one); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); DEPRECATED_OP_TYPES.put(DataApiOpType.estimated_document_count, DataApiOpType.collection_estimated_document_count); } @@ -103,7 +104,6 @@ public class DataApiOpMapper implements OpMapper { case insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); - case update_one -> new DataApiCollectionLegacyUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -124,6 +124,7 @@ public class DataApiOpMapper implements OpMapper { case find_by_id -> new DataApiCollectionLegacyFindByIdOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_distinct -> new DataApiCollectionLegacyFindDistinctOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one -> new DataApiCollectionLegacyFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case update_one -> new DataApiCollectionLegacyUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case count_documents -> new DataApiCollectionLegacyCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); case estimated_document_count -> @@ -133,6 +134,7 @@ public class DataApiOpMapper implements OpMapper { // in-collection ops: case collection_find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java new file mode 100644 index 000000000..ec47efee5 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.collections.commands.options.CollectionUpdateOneOptions; +import com.datastax.astra.client.core.query.Sort; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.collections.commands.Update; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionUpdateOneOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Map; +import java.util.Optional; +import java.util.function.LongFunction; + +public class DataApiCollectionUpdateOneOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionUpdateOneOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionUpdateOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getFilterFromOp(op, l); + CollectionUpdateOneOptions options = getCollectionUpdateOneOptions(op, l); + Update update = getUpdateFromOp(op, l); + + return new DataApiCollectionUpdateOneOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + update, + options + ); + }; + } + + private CollectionUpdateOneOptions getCollectionUpdateOneOptions(ParsedOp op, long l) { + CollectionUpdateOneOptions options = new CollectionUpdateOneOptions(); + Sort sort = getSortFromOp(op, l); + Boolean upsert = getUpsertFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + if ( upsert != null ){ + options = options.upsert(upsert); + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index e0ae1558e..710ba8712 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -37,7 +37,6 @@ public enum DataApiOpType { insert_many, insert_one, insert_one_vector, - update_one, update_many, find_one_and_delete, replace_one, @@ -58,6 +57,7 @@ public enum DataApiOpType { find_by_id, find_distinct, find_one, + update_one, find_one_and_update, estimated_document_count, count_documents, @@ -71,6 +71,7 @@ public enum DataApiOpType { collection_delete_one, collection_find, collection_find_one, + collection_update_one, collection_find_one_and_update, collection_estimated_document_count, collection_count_documents, From 73ad2a44f49bdf6db566bf17e1b1555f7d31de1c Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 14 Sep 2026 17:46:24 +0200 Subject: [PATCH 29/46] find_one_and_delete: legacy/new split, revise syntax parsing - done --- .../adapter/dataapi/DataApiOpMapper.java | 4 +- ...tionLegacyFindOneAndDeleteOpDispenser.java | 74 +++++++++++++++++++ .../adapter/dataapi/ops/DataApiOpType.java | 3 +- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 6a1ba47d5..60528b08b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -45,6 +45,7 @@ public class DataApiOpMapper implements OpMapper { DEPRECATED_OP_TYPES.put(DataApiOpType.delete_all, DataApiOpType.collection_delete_many); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_many, DataApiOpType.collection_delete_many); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_one, DataApiOpType.collection_delete_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_delete, DataApiOpType.collection_find_one_and_delete); DEPRECATED_OP_TYPES.put(DataApiOpType.find, DataApiOpType.collection_find); DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector, DataApiOpType.collection_find); DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector_filter, DataApiOpType.collection_find); @@ -105,7 +106,6 @@ public class DataApiOpMapper implements OpMapper { case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -118,6 +118,7 @@ public class DataApiOpMapper implements OpMapper { case delete_one -> new DataApiCollectionLegacyDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_many -> new DataApiCollectionLegacyDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_all -> new DataApiCollectionLegacyDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_one_and_delete -> new DataApiCollectionLegacyFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case find -> new DataApiCollectionLegacyFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector -> new DataApiCollectionLegacyFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_vector_filter -> new DataApiCollectionLegacyFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -138,6 +139,7 @@ public class DataApiOpMapper implements OpMapper { case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java new file mode 100644 index 000000000..6c9fa9d2a --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.collections.commands.options.CollectionFindOneAndDeleteOptions; +import com.datastax.astra.client.core.query.Projection; +import com.datastax.astra.client.core.query.Sort; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOneAndDeleteOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyFindOneAndDeleteOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindOneAndDeleteOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionLegacyFindOneAndDeleteOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getLegacyFilterFromOp(op, l); + CollectionFindOneAndDeleteOptions options = getCollectionFindOneAndDeleteOptions(op, l); + + return new DataApiCollectionFindOneAndDeleteOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + options + ); + }; + } + + private CollectionFindOneAndDeleteOptions getCollectionFindOneAndDeleteOptions(ParsedOp op, long l) { + CollectionFindOneAndDeleteOptions options = new CollectionFindOneAndDeleteOptions(); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + Projection[] projection = getProjectionFromOp(op, l); + if (projection != null) { + options = options.projection(projection); + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 710ba8712..6bbf5ac6d 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -38,7 +38,6 @@ public enum DataApiOpType { insert_one, insert_one_vector, update_many, - find_one_and_delete, replace_one, find_one_and_replace, @@ -51,6 +50,7 @@ public enum DataApiOpType { delete_one, delete_many, delete_all, + find_one_and_delete, find, find_vector, find_vector_filter, @@ -69,6 +69,7 @@ public enum DataApiOpType { // in-collection ops: collection_delete_many, collection_delete_one, + collection_find_one_and_delete, collection_find, collection_find_one, collection_update_one, From a2a4be806dd6d644525ef870609baf10b045ecdd Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:12:46 +0200 Subject: [PATCH 30/46] findOneAndReplace, fully reworked --- .../adapter/dataapi/DataApiOpMapper.java | 5 +- ...ollectionFindOneAndReplaceOpDispenser.java | 17 ++-- ...ionLegacyFindOneAndReplaceOpDispenser.java | 92 +++++++++++++++++++ .../opdispensers/DataApiOpDispenser.java | 14 +++ .../adapter/dataapi/ops/DataApiOpType.java | 3 +- 5 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 60528b08b..3acd2db21 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -54,6 +54,8 @@ public class DataApiOpMapper implements OpMapper { DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); DEPRECATED_OP_TYPES.put(DataApiOpType.update_one, DataApiOpType.collection_update_one); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_replace, DataApiOpType.collection_find_one_and_replace); + DEPRECATED_OP_TYPES.put(DataApiOpType.count_documents, DataApiOpType.collection_count_documents); DEPRECATED_OP_TYPES.put(DataApiOpType.estimated_document_count, DataApiOpType.collection_estimated_document_count); } @@ -107,7 +109,6 @@ public class DataApiOpMapper implements OpMapper { case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); - case find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); // LEGACY OPS // admin ops: @@ -127,6 +128,7 @@ public class DataApiOpMapper implements OpMapper { case find_one -> new DataApiCollectionLegacyFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_one -> new DataApiCollectionLegacyUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + case find_one_and_replace -> new DataApiCollectionLegacyFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); case count_documents -> new DataApiCollectionLegacyCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); case estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -140,6 +142,7 @@ public class DataApiOpMapper implements OpMapper { case collection_delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java index 42f5f631f..62665cf74 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java @@ -48,7 +48,7 @@ public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDisp Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getFilterFromOp(op, l); CollectionFindOneAndReplaceOptions options = getCollectionFindOneAndReplaceOptions(op, l); - LongFunction docMapFunc = op.getAsRequiredFunction("document", Map.class); + LongFunction docMapFunc = op.getAsRequiredFunction("replacement", Map.class); LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); return new DataApiCollectionFindOneAndReplaceOp( @@ -71,16 +71,13 @@ public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDisp if (projection != null) { options = options.projection(projection); } - Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); - if (upsertFunction.isPresent()) { - options = options.upsert(upsertFunction.get().apply(l)); + Boolean upsert = getUpsertFromOp(op, l); + if (upsert != null) { + options = options.upsert(upsert); } - if (op.isDefined("returnDocument")) { - options = switch ((String) op.get("returnDocument", l)) { - case "after" -> options.returnDocument(ReturnDocument.AFTER); - case "before" -> options.returnDocument(ReturnDocument.BEFORE); - default -> throw new RuntimeException("Invalid returnDocument value: " + op.get("returnDocument", l)); - }; + ReturnDocument returnDocument = getReturnDocumentFromOp(op, l); + if (returnDocument != null){ + options = options.returnDocument(returnDocument); } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java new file mode 100644 index 000000000..970c274ed --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import com.datastax.astra.client.collections.commands.ReturnDocument; +import com.datastax.astra.client.collections.commands.options.CollectionFindOneAndReplaceOptions; +import com.datastax.astra.client.core.query.Projection; +import com.datastax.astra.client.core.query.Sort; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import com.datastax.astra.client.collections.definition.documents.Document; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindOneAndReplaceOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Map; +import java.util.Optional; +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyFindOneAndReplaceOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyFindOneAndReplaceOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionLegacyFindOneAndReplaceOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getLegacyFilterFromOp(op, l); + CollectionFindOneAndReplaceOptions options = getCollectionFindOneAndReplaceOptions(op, l); + LongFunction docMapFunc = op.getAsRequiredFunction("document", Map.class); + LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); + + return new DataApiCollectionFindOneAndReplaceOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + docFunc.apply(l), + options + ); + }; + } + + private CollectionFindOneAndReplaceOptions getCollectionFindOneAndReplaceOptions(ParsedOp op, long l) { + CollectionFindOneAndReplaceOptions options = new CollectionFindOneAndReplaceOptions(); + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + Projection[] projection = getProjectionFromOp(op, l); + if (projection != null) { + options = options.projection(projection); + } + Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); + if (upsertFunction.isPresent()) { + options = options.upsert(upsertFunction.get().apply(l)); + } + if (op.isDefined("returnDocument")) { + options = switch ((String) op.get("returnDocument", l)) { + case "after" -> options.returnDocument(ReturnDocument.AFTER); + case "before" -> options.returnDocument(ReturnDocument.BEFORE); + default -> throw new RuntimeException("Invalid returnDocument value: " + op.get("returnDocument", l)); + }; + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 7cc4fe467..763a54c31 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -20,6 +20,7 @@ import com.datastax.astra.client.core.query.Filter; import com.datastax.astra.client.core.query.Filters; import com.datastax.astra.client.collections.definition.CollectionDefinition; import com.datastax.astra.client.collections.definition.CollectionDefaultIdTypes; +import com.datastax.astra.client.collections.commands.ReturnDocument; import com.datastax.astra.client.collections.commands.Update; import com.datastax.astra.client.collections.commands.Updates; import com.datastax.astra.client.core.query.Sort; @@ -207,6 +208,19 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> rdf = op.getAsOptionalFunction("return_document", String.class); + if (rdf.isPresent()) { + String rdValue = rdf.get().apply(l); + return switch (rdValue) { + case "after" -> ReturnDocument.AFTER; + case "before" -> ReturnDocument.BEFORE; + default -> throw new RuntimeException("Invalid returnDocument value: " + op.get("return_document", l)); + }; + } + return null; + } + protected Optional getIncludeSimilarityFromOp(ParsedOp op, long l) { Optional> includeSimFunction = op.getAsOptionalFunction("include_similarity", Boolean.class); if (includeSimFunction.isPresent()) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 6bbf5ac6d..88655f183 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -39,7 +39,6 @@ public enum DataApiOpType { insert_one_vector, update_many, replace_one, - find_one_and_replace, // LEGACY OPS // admin ops: @@ -59,6 +58,7 @@ public enum DataApiOpType { find_one, update_one, find_one_and_update, + find_one_and_replace, estimated_document_count, count_documents, @@ -74,6 +74,7 @@ public enum DataApiOpType { collection_find_one, collection_update_one, collection_find_one_and_update, + collection_find_one_and_replace, collection_estimated_document_count, collection_count_documents, } From 917524490a013719f225f8270e9babf032a69c08 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:36:11 +0200 Subject: [PATCH 31/46] create and use getReplacementFromOp --- .../DataApiCollectionFindOneAndReplaceOpDispenser.java | 6 ++---- .../dataapi/opdispensers/DataApiOpDispenser.java | 10 +++++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java index 62665cf74..fe358d520 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java @@ -31,7 +31,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.Map; -import java.util.Optional; import java.util.function.LongFunction; public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDispenser { @@ -48,14 +47,13 @@ public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDisp Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getFilterFromOp(op, l); CollectionFindOneAndReplaceOptions options = getCollectionFindOneAndReplaceOptions(op, l); - LongFunction docMapFunc = op.getAsRequiredFunction("replacement", Map.class); - LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); + Document replacement = getReplacementFromOp(op, l); return new DataApiCollectionFindOneAndReplaceOp( db, db.getCollection(targetFunction.apply(l)), filter, - docFunc.apply(l), + replacement, options ); }; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 763a54c31..48b7b1b8a 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -20,6 +20,7 @@ import com.datastax.astra.client.core.query.Filter; import com.datastax.astra.client.core.query.Filters; import com.datastax.astra.client.collections.definition.CollectionDefinition; import com.datastax.astra.client.collections.definition.CollectionDefaultIdTypes; +import com.datastax.astra.client.collections.definition.documents.Document; import com.datastax.astra.client.collections.commands.ReturnDocument; import com.datastax.astra.client.collections.commands.Update; import com.datastax.astra.client.collections.commands.Updates; @@ -92,6 +93,11 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser docMap = getFreeFormFromOp(op, l, "replacement", true); + return new Document(docMap); + } + protected void addOperatorFilter(List filtersList, String operator, String fieldName, Object fieldValue) { switch (operator) { case "all" -> @@ -256,7 +262,9 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser Date: Wed, 16 Sep 2026 23:02:03 +0200 Subject: [PATCH 32/46] replaceOne reworked (only legacy, it's not a data api primitive) --- .../adapter/dataapi/DataApiOpMapper.java | 7 ++-- ...ollectionFindOneAndReplaceOpDispenser.java | 1 - ...ollectionLegacyReplaceOneOpDispenser.java} | 35 ++++++++++++++----- ... DataApiCollectionLegacyReplaceOneOp.java} | 4 +-- 4 files changed, 32 insertions(+), 15 deletions(-) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionReplaceOneOpDispenser.java => DataApiCollectionLegacyReplaceOneOpDispenser.java} (62%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionReplaceOneOp.java => DataApiCollectionLegacyReplaceOneOp.java} (85%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 3acd2db21..158d0f8f4 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -49,11 +49,12 @@ public class DataApiOpMapper implements OpMapper { DEPRECATED_OP_TYPES.put(DataApiOpType.find, DataApiOpType.collection_find); DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector, DataApiOpType.collection_find); DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector_filter, DataApiOpType.collection_find); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_by_id, null); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_by_id, DataApiOpType.collection_find_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); // not a Data API primitive, it's client-emulated DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); DEPRECATED_OP_TYPES.put(DataApiOpType.update_one, DataApiOpType.collection_update_one); DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); + DEPRECATED_OP_TYPES.put(DataApiOpType.replace_one, null); // not a Data API primitive, it's client-emulated DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_replace, DataApiOpType.collection_find_one_and_replace); DEPRECATED_OP_TYPES.put(DataApiOpType.count_documents, DataApiOpType.collection_count_documents); DEPRECATED_OP_TYPES.put(DataApiOpType.estimated_document_count, DataApiOpType.collection_estimated_document_count); @@ -108,7 +109,6 @@ public class DataApiOpMapper implements OpMapper { case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); - case replace_one -> new DataApiCollectionReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); // LEGACY OPS // admin ops: @@ -128,6 +128,7 @@ public class DataApiOpMapper implements OpMapper { case find_one -> new DataApiCollectionLegacyFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case update_one -> new DataApiCollectionLegacyUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); + case replace_one -> new DataApiCollectionLegacyReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_replace -> new DataApiCollectionLegacyFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); case count_documents -> new DataApiCollectionLegacyCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); case estimated_document_count -> diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java index fe358d520..3f81d59d7 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java @@ -30,7 +30,6 @@ import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.util.Map; import java.util.function.LongFunction; public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDispenser { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionReplaceOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java similarity index 62% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionReplaceOneOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java index 8e46ab504..ff5f2a07f 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionReplaceOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java @@ -18,11 +18,14 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.core.query.Projection; +import com.datastax.astra.client.core.query.Sort; +import com.datastax.astra.client.collections.commands.ReturnDocument; import com.datastax.astra.client.collections.commands.options.CollectionReplaceOneOptions; import com.datastax.astra.client.collections.definition.documents.Document; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionReplaceOneOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyReplaceOneOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -31,24 +34,24 @@ import java.util.Map; import java.util.Optional; import java.util.function.LongFunction; -public class DataApiCollectionReplaceOneOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionReplaceOneOpDispenser.class); - private final LongFunction opFunction; +public class DataApiCollectionLegacyReplaceOneOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyReplaceOneOpDispenser.class); + private final LongFunction opFunction; - public DataApiCollectionReplaceOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + public DataApiCollectionLegacyReplaceOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getFilterFromOp(op, l); + Filter filter = getLegacyFilterFromOp(op, l); CollectionReplaceOneOptions options = getCollectionReplaceOneOptions(op, l); LongFunction docMapFunc = op.getAsRequiredFunction("document", Map.class); LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); - return new DataApiCollectionReplaceOneOp( + return new DataApiCollectionLegacyReplaceOneOp( db, db.getCollection(targetFunction.apply(l)), filter, @@ -60,11 +63,25 @@ public class DataApiCollectionReplaceOneOpDispenser extends DataApiOpDispenser { private CollectionReplaceOneOptions getCollectionReplaceOneOptions(ParsedOp op, long l) { CollectionReplaceOneOptions options = new CollectionReplaceOneOptions(); - + Sort sort = getSortFromOp(op, l); + if (sort != null) { + options = options.sort(sort); + } + Projection[] projection = getProjectionFromOp(op, l); + if (projection != null) { + options = options.projection(projection); + } Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); if (upsertFunction.isPresent()) { options = options.upsert(upsertFunction.get().apply(l)); } + if (op.isDefined("returnDocument")) { + options = switch ((String) op.get("returnDocument", l)) { + case "after" -> options.returnDocument(ReturnDocument.AFTER); + case "before" -> options.returnDocument(ReturnDocument.BEFORE); + default -> throw new RuntimeException("Invalid returnDocument value: " + op.get("returnDocument", l)); + }; + } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionReplaceOneOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyReplaceOneOp.java similarity index 85% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionReplaceOneOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyReplaceOneOp.java index 26e254972..6041860e6 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionReplaceOneOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyReplaceOneOp.java @@ -21,13 +21,13 @@ import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.core.query.Filter; import com.datastax.astra.client.collections.commands.options.CollectionReplaceOneOptions; -public class DataApiCollectionReplaceOneOp extends DataApiBaseOp { +public class DataApiCollectionLegacyReplaceOneOp extends DataApiBaseOp { private final Collection collection; private final Filter filter; private final Object replacement; private final CollectionReplaceOneOptions options; - public DataApiCollectionReplaceOneOp(Database db, Collection collection, Filter filter, Object replacement, CollectionReplaceOneOptions options) { + public DataApiCollectionLegacyReplaceOneOp(Database db, Collection collection, Filter filter, Object replacement, CollectionReplaceOneOptions options) { super(db); this.collection = collection; this.filter = filter; From 7117dfaf63509f53a2aeebc5ba1f66ee483841f8 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Wed, 16 Sep 2026 23:36:37 +0200 Subject: [PATCH 33/46] updateMany reworked (legacy+newstyle) --- .../adapter/dataapi/DataApiOpMapper.java | 4 +- ...CollectionLegacyUpdateManyOpDispenser.java | 74 +++++++++++++++++++ ...ataApiCollectionUpdateManyOpDispenser.java | 13 ++-- .../adapter/dataapi/ops/DataApiOpType.java | 5 +- 4 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 158d0f8f4..5888c2722 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -56,6 +56,7 @@ public class DataApiOpMapper implements OpMapper { DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); DEPRECATED_OP_TYPES.put(DataApiOpType.replace_one, null); // not a Data API primitive, it's client-emulated DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_replace, DataApiOpType.collection_find_one_and_replace); + DEPRECATED_OP_TYPES.put(DataApiOpType.update_many, DataApiOpType.collection_update_many); DEPRECATED_OP_TYPES.put(DataApiOpType.count_documents, DataApiOpType.collection_count_documents); DEPRECATED_OP_TYPES.put(DataApiOpType.estimated_document_count, DataApiOpType.collection_estimated_document_count); } @@ -108,7 +109,6 @@ public class DataApiOpMapper implements OpMapper { case insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); - case update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); // LEGACY OPS // admin ops: @@ -130,6 +130,7 @@ public class DataApiOpMapper implements OpMapper { case find_one_and_update -> new DataApiCollectionLegacyFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case replace_one -> new DataApiCollectionLegacyReplaceOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case find_one_and_replace -> new DataApiCollectionLegacyFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); + case update_many -> new DataApiCollectionLegacyUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case count_documents -> new DataApiCollectionLegacyCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); case estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -144,6 +145,7 @@ public class DataApiOpMapper implements OpMapper { case collection_delete_one -> new DataApiCollectionDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_delete -> new DataApiCollectionFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_replace -> new DataApiCollectionFindOneAndReplaceOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_update_many -> new DataApiCollectionUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_estimated_document_count -> new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_count_documents -> new DataApiCollectionCountDocumentsOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java new file mode 100644 index 000000000..6cfe17396 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.collections.commands.Update; +import com.datastax.astra.client.collections.commands.options.CollectionUpdateManyOptions; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionUpdateManyOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Map; +import java.util.Optional; +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyUpdateManyOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyUpdateManyOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionLegacyUpdateManyOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getLegacyFilterFromOp(op, l); + CollectionUpdateManyOptions options = getCollectionUpdateManyOptions(op, l); + LongFunction docMapFunc = op.getAsRequiredFunction("updates", Map.class); + + return new DataApiCollectionUpdateManyOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + new Update(docMapFunc.apply(l)), + options + ); + }; + } + + private CollectionUpdateManyOptions getCollectionUpdateManyOptions(ParsedOp op, long l) { + CollectionUpdateManyOptions options = new CollectionUpdateManyOptions(); + Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); + if (upsertFunction.isPresent()) { + options = options.upsert(upsertFunction.get().apply(l)); + } + + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateManyOpDispenser.java index 7a920d7c4..f37860095 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateManyOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateManyOpDispenser.java @@ -27,8 +27,6 @@ import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.util.Map; -import java.util.Optional; import java.util.function.LongFunction; public class DataApiCollectionUpdateManyOpDispenser extends DataApiOpDispenser { @@ -45,13 +43,13 @@ public class DataApiCollectionUpdateManyOpDispenser extends DataApiOpDispenser { Database db = spaceFunction.apply(l).getDatabase(); Filter filter = getFilterFromOp(op, l); CollectionUpdateManyOptions options = getCollectionUpdateManyOptions(op, l); - LongFunction docMapFunc = op.getAsRequiredFunction("updates", Map.class); + Update update = getUpdateFromOp(op, l); return new DataApiCollectionUpdateManyOp( db, db.getCollection(targetFunction.apply(l)), filter, - new Update(docMapFunc.apply(l)), + update, options ); }; @@ -59,11 +57,10 @@ public class DataApiCollectionUpdateManyOpDispenser extends DataApiOpDispenser { private CollectionUpdateManyOptions getCollectionUpdateManyOptions(ParsedOp op, long l) { CollectionUpdateManyOptions options = new CollectionUpdateManyOptions(); - Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); - if (upsertFunction.isPresent()) { - options = options.upsert(upsertFunction.get().apply(l)); + Boolean upsert = getUpsertFromOp(op, l); + if (upsert != null) { + options = options.upsert(upsert); } - return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 88655f183..0af862c0a 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -37,8 +37,6 @@ public enum DataApiOpType { insert_many, insert_one, insert_one_vector, - update_many, - replace_one, // LEGACY OPS // admin ops: @@ -58,7 +56,9 @@ public enum DataApiOpType { find_one, update_one, find_one_and_update, + replace_one, find_one_and_replace, + update_many, estimated_document_count, count_documents, @@ -75,6 +75,7 @@ public enum DataApiOpType { collection_update_one, collection_find_one_and_update, collection_find_one_and_replace, + collection_update_many, collection_estimated_document_count, collection_count_documents, } From 68d90231c78dbd1653cfbce19892ede8dab9e08e Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 17 Sep 2026 10:14:36 +0200 Subject: [PATCH 34/46] reworked insertOne and 'insert one vector' (legacy+newstyle) --- .../adapter/dataapi/DataApiOpMapper.java | 7 +++++-- ...ctionLegacyInsertOneVectorOpDispenser.java} | 18 ++++++++---------- ...aApiCollectionLegacyInsertOneVectorOp.java} | 4 ++-- .../adapter/dataapi/ops/DataApiOpType.java | 5 +++-- 4 files changed, 18 insertions(+), 16 deletions(-) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCollectionInsertOneVectorOpDispenser.java => DataApiCollectionLegacyInsertOneVectorOpDispenser.java} (68%) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCollectionInsertOneVectorOp.java => DataApiCollectionLegacyInsertOneVectorOp.java} (87%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 5888c2722..d14ca5994 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -42,6 +42,8 @@ public class DataApiOpMapper implements OpMapper { // db-admin ops: // in-database ops: // in-collection ops: + DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one, DataApiOpType.collection_insert_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one_vector, DataApiOpType.collection_insert_one); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_all, DataApiOpType.collection_delete_many); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_many, DataApiOpType.collection_delete_many); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_one, DataApiOpType.collection_delete_one); @@ -107,8 +109,6 @@ public class DataApiOpMapper implements OpMapper { new DataApiListCollectionNamesOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); - case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); - case insert_one_vector -> new DataApiCollectionInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); // LEGACY OPS // admin ops: @@ -116,6 +116,8 @@ public class DataApiOpMapper implements OpMapper { // in-database ops: case create_collection_with_class -> new DataApiLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: + case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case insert_one_vector -> new DataApiCollectionLegacyInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_one -> new DataApiCollectionLegacyDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_many -> new DataApiCollectionLegacyDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_all -> new DataApiCollectionLegacyDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -137,6 +139,7 @@ public class DataApiOpMapper implements OpMapper { // NEW-STYLE OPS // in-collection ops: + case collection_insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertOneVectorOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyInsertOneVectorOpDispenser.java similarity index 68% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertOneVectorOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyInsertOneVectorOpDispenser.java index b157f921c..1278ce106 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertOneVectorOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyInsertOneVectorOpDispenser.java @@ -19,8 +19,7 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import com.datastax.astra.client.collections.definition.documents.Document; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionInsertOneOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionInsertOneVectorOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionLegacyInsertOneVectorOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -28,25 +27,24 @@ import org.apache.logging.log4j.Logger; import java.util.Map; import java.util.function.LongFunction; -public class DataApiCollectionInsertOneVectorOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCollectionInsertOneVectorOpDispenser.class); - private final LongFunction opFunction; +public class DataApiCollectionLegacyInsertOneVectorOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyInsertOneVectorOpDispenser.class); + private final LongFunction opFunction; - public DataApiCollectionInsertOneVectorOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + public DataApiCollectionLegacyInsertOneVectorOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { LongFunction docMapFunc = op.getAsRequiredFunction("document", Map.class); LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); - LongFunction vectorF= op.getAsRequiredFunction("vector", float[].class); return (l) -> { - return new DataApiCollectionInsertOneVectorOp( + return new DataApiCollectionLegacyInsertOneVectorOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), docFunc.apply(l), - vectorF.apply(l) + getVectorValues(op, l) ); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionInsertOneVectorOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyInsertOneVectorOp.java similarity index 87% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionInsertOneVectorOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyInsertOneVectorOp.java index 1c0d4e635..38a763eac 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionInsertOneVectorOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionLegacyInsertOneVectorOp.java @@ -21,11 +21,11 @@ import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.collections.definition.documents.Document; import com.datastax.astra.client.collections.commands.results.CollectionInsertOneResult; -public class DataApiCollectionInsertOneVectorOp extends DataApiBaseOp { +public class DataApiCollectionLegacyInsertOneVectorOp extends DataApiBaseOp { private final Document doc; private final String collectionName; - public DataApiCollectionInsertOneVectorOp(Database db, String collectionName, Document doc, float[] vector) { + public DataApiCollectionLegacyInsertOneVectorOp(Database db, String collectionName, Document doc, float[] vector) { super(db); this.collectionName = collectionName; this.doc = doc.vector(vector); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 0af862c0a..655ad0a56 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -35,8 +35,6 @@ public enum DataApiOpType { list_collection_names, // in-collection ops: insert_many, - insert_one, - insert_one_vector, // LEGACY OPS // admin ops: @@ -44,6 +42,8 @@ public enum DataApiOpType { // in-database ops: create_collection_with_class, // in-collection ops: + insert_one, + insert_one_vector, delete_one, delete_many, delete_all, @@ -67,6 +67,7 @@ public enum DataApiOpType { // db-admin ops: // in-database ops: // in-collection ops: + collection_insert_one, collection_delete_many, collection_delete_one, collection_find_one_and_delete, From 4945fe5480743c700d56198986f1162176e1d6f3 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:19:20 +0200 Subject: [PATCH 35/46] insertMany, legacy+newstyle reworked entirely --- .../adapter/dataapi/DataApiOpMapper.java | 5 +- ...ataApiCollectionInsertManyOpDispenser.java | 27 +++---- ...DataApiCollectionInsertOneOpDispenser.java | 5 +- ...CollectionLegacyInsertManyOpDispenser.java | 81 +++++++++++++++++++ .../opdispensers/DataApiOpDispenser.java | 44 ++++++++++ .../adapter/dataapi/ops/DataApiOpType.java | 4 +- 6 files changed, 142 insertions(+), 24 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyInsertManyOpDispenser.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index d14ca5994..e2f546e09 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -44,6 +44,7 @@ public class DataApiOpMapper implements OpMapper { // in-collection ops: DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one, DataApiOpType.collection_insert_one); DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one_vector, DataApiOpType.collection_insert_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.insert_many, DataApiOpType.collection_insert_many); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_all, DataApiOpType.collection_delete_many); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_many, DataApiOpType.collection_delete_many); DEPRECATED_OP_TYPES.put(DataApiOpType.delete_one, DataApiOpType.collection_delete_one); @@ -107,8 +108,6 @@ public class DataApiOpMapper implements OpMapper { case list_collections -> new DataApiListCollectionsOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collection_names -> new DataApiListCollectionNamesOpDispenser(adapter, op, typeAndTarget.targetFunction); - // in-collection ops: - case insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); // LEGACY OPS // admin ops: @@ -118,6 +117,7 @@ public class DataApiOpMapper implements OpMapper { // in-collection ops: case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionLegacyInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); + case insert_many -> new DataApiCollectionLegacyInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_one -> new DataApiCollectionLegacyDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_many -> new DataApiCollectionLegacyDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_all -> new DataApiCollectionLegacyDeleteAllOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -140,6 +140,7 @@ public class DataApiOpMapper implements OpMapper { // NEW-STYLE OPS // in-collection ops: case collection_insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertManyOpDispenser.java index 659aa90aa..040b4c677 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertManyOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertManyOpDispenser.java @@ -42,8 +42,7 @@ public class DataApiCollectionInsertManyOpDispenser extends DataApiOpDispenser { private LongFunction createOpFunction(ParsedOp op) { return (l) -> { - List documents = new ArrayList<>(); - op.getAsRequiredFunction("documents", List.class).apply(l).forEach(o -> documents.add(Document.parse(o.toString()))); + List documents = getDocumentsFromOp(op, l); return new DataApiCollectionInsertManyOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), @@ -55,21 +54,15 @@ public class DataApiCollectionInsertManyOpDispenser extends DataApiOpDispenser { private CollectionInsertManyOptions getCollectionInsertManyOptions(ParsedOp op, long l) { CollectionInsertManyOptions options = new CollectionInsertManyOptions(); - Optional> optionsFunction = op.getAsOptionalFunction("options", Map.class); - if (optionsFunction.isPresent()) { - Map optionFields = optionsFunction.get().apply(l); - for(Map.Entry entry: optionFields.entrySet()) { - switch(entry.getKey()) { - case "chunkSize"-> - options = options.chunkSize(Integer.parseInt(entry.getValue())); - case "concurrency" -> - options = options.concurrency(Integer.parseInt(entry.getValue())); - case "ordered" -> - options = options.ordered(Boolean.parseBoolean(entry.getValue())); - case "timeout" -> - options = options.timeout(Integer.parseInt(entry.getValue())); - } - } + options = options.concurrency(1); // hardcoded: avoid client concurrency, let NB use its own. + Integer chunkSize = getChunkSizeFromOp(op, l); + if (chunkSize != null) { + logger.warn(() -> "Setting insertion 'chunk_size'. This is discouraged, as it usually signals an intention to not have 1:1 between ops and HTTP requests."); + options = options.chunkSize(chunkSize); + } + Boolean ordered = getOrderedFromOp(op, l); + if (ordered != null) { + options = options.ordered(ordered); } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertOneOpDispenser.java index 072bcb1a4..4ea489e34 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionInsertOneOpDispenser.java @@ -37,13 +37,12 @@ public class DataApiCollectionInsertOneOpDispenser extends DataApiOpDispenser { } private LongFunction createOpFunction(ParsedOp op) { - LongFunction docMapFunc = op.getAsRequiredFunction("document", Map.class); - LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); return (l) -> { + Document document = getDocumentFromOp(op, l); return new DataApiCollectionInsertOneOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), - docFunc.apply(l) + document ); }; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyInsertManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyInsertManyOpDispenser.java new file mode 100644 index 000000000..a5b2a2c4f --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyInsertManyOpDispenser.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.collections.definition.documents.Document; +import com.datastax.astra.client.collections.commands.options.CollectionInsertManyOptions; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionInsertManyOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.LongFunction; + +public class DataApiCollectionLegacyInsertManyOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionLegacyInsertManyOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionLegacyInsertManyOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + List documents = new ArrayList<>(); + op.getAsRequiredFunction("documents", List.class).apply(l).forEach(o -> documents.add(Document.parse(o.toString()))); + return new DataApiCollectionInsertManyOp( + spaceFunction.apply(l).getDatabase(), + targetFunction.apply(l), + documents, + getCollectionInsertManyOptions(op, l) + ); + }; + } + + private CollectionInsertManyOptions getCollectionInsertManyOptions(ParsedOp op, long l) { + CollectionInsertManyOptions options = new CollectionInsertManyOptions(); + Optional> optionsFunction = op.getAsOptionalFunction("options", Map.class); + if (optionsFunction.isPresent()) { + Map optionFields = optionsFunction.get().apply(l); + for(Map.Entry entry: optionFields.entrySet()) { + switch(entry.getKey()) { + case "chunkSize"-> + options = options.chunkSize(Integer.parseInt(entry.getValue())); + case "concurrency" -> + options = options.concurrency(Integer.parseInt(entry.getValue())); + case "ordered" -> + options = options.ordered(Boolean.parseBoolean(entry.getValue())); + case "timeout" -> + options = options.timeout(Integer.parseInt(entry.getValue())); + } + } + } + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 48b7b1b8a..14b3e931c 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -98,6 +98,16 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser docMap = getFreeFormFromOp(op, l, "document", true); + return new Document(docMap); + } + + protected List getDocumentsFromOp(ParsedOp op, long l) { + List> docMapList = getFreeFormListFromOp(op, l, "documents", true); + return docMapList.stream().map(Document::new).toList(); + } + protected void addOperatorFilter(List filtersList, String operator, String fieldName, Object fieldValue) { switch (operator) { case "all" -> @@ -214,6 +224,24 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> csFunction = op.getAsOptionalFunction("chunk_size", Integer.class); + if (csFunction.isPresent()) { + LongFunction cs = csFunction.get(); + return cs.apply(l); + } + return null; + } + + protected Boolean getOrderedFromOp(ParsedOp op, long l) { + Optional> orderedFunction = op.getAsOptionalFunction("ordered", Boolean.class); + if (orderedFunction.isPresent()) { + LongFunction of = orderedFunction.get(); + return of.apply(l); + } + return null; + } + protected ReturnDocument getReturnDocumentFromOp(ParsedOp op, long l) { Optional> rdf = op.getAsOptionalFunction("return_document", String.class); if (rdf.isPresent()) { @@ -270,6 +298,22 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> getFreeFormListFromOp(ParsedOp op, long l, String fieldName, Boolean required) { + Optional> ffMapFunc = op.getAsOptionalFunction(fieldName, List.class); + if (ffMapFunc.isPresent()) { + LongFunction dmf = ffMapFunc.get(); + return dmf.apply(l); + } else { + if (required) { + throw new OpConfigError( + "Required field '" + fieldName + "' not supplied." + ); + } + return null; + } + } + /* LEGACY OP DISPENSER UTILS START HERE */ /* diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 655ad0a56..010fa93f2 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -33,8 +33,6 @@ public enum DataApiOpType { delete_collection, list_collections, list_collection_names, - // in-collection ops: - insert_many, // LEGACY OPS // admin ops: @@ -44,6 +42,7 @@ public enum DataApiOpType { // in-collection ops: insert_one, insert_one_vector, + insert_many, delete_one, delete_many, delete_all, @@ -68,6 +67,7 @@ public enum DataApiOpType { // in-database ops: // in-collection ops: collection_insert_one, + collection_insert_many, collection_delete_many, collection_delete_one, collection_find_one_and_delete, From f381e22beb658aeb4feb21fbed89fd662f72ea3b Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Mon, 21 Sep 2026 22:38:27 +0200 Subject: [PATCH 36/46] legacy createCollection: allow vecze params without apikey --- nb-adapters/adapter-dataapi/pom.xml | 2 +- .../adapter/dataapi/opdispensers/DataApiOpDispenser.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/nb-adapters/adapter-dataapi/pom.xml b/nb-adapters/adapter-dataapi/pom.xml index 2f4ab31b5..cbf0be2c0 100644 --- a/nb-adapters/adapter-dataapi/pom.xml +++ b/nb-adapters/adapter-dataapi/pom.xml @@ -49,7 +49,7 @@ com.datastax.astra astra-db-java - 2.3.0 + 2.3.2 diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 14b3e931c..c646f10a0 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -430,8 +430,11 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser Date: Tue, 22 Sep 2026 17:44:11 +0200 Subject: [PATCH 37/46] reinstated the new/legacy createCollection ops after a revert-merge-commit git mess --- .../adapter/dataapi/DataApiOpMapper.java | 47 ++++++++-------- .../DataApiDbCreateCollectionOpDispenser.java | 56 +++++++++++++++++++ ...ApiLegacyCreateCollectionOpDispenser.java} | 17 +++--- .../opdispensers/DataApiOpDispenser.java | 13 +---- .../ops/DataApiDbCreateCollectionOp.java | 43 ++++++++++++++ ...a => DataApiLegacyCreateCollectionOp.java} | 4 +- .../adapter/dataapi/ops/DataApiOpType.java | 3 +- 7 files changed, 139 insertions(+), 44 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbCreateCollectionOpDispenser.java rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiCreateCollectionOpDispenser.java => DataApiLegacyCreateCollectionOpDispenser.java} (70%) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbCreateCollectionOp.java rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiCreateCollectionOp.java => DataApiLegacyCreateCollectionOp.java} (85%) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index e2f546e09..55c2b6cc3 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -38,30 +38,31 @@ public class DataApiOpMapper implements OpMapper { static { DEPRECATED_OP_TYPES = new HashMap<>(); // admin ops: - DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection_with_class, null); // TODO => newstyle create coll. + DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection_with_class, DataApiOpType.db_create_collection); + DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection, DataApiOpType.db_create_collection); // db-admin ops: // in-database ops: // in-collection ops: - DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one, DataApiOpType.collection_insert_one); - DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one_vector, DataApiOpType.collection_insert_one); - DEPRECATED_OP_TYPES.put(DataApiOpType.insert_many, DataApiOpType.collection_insert_many); - DEPRECATED_OP_TYPES.put(DataApiOpType.delete_all, DataApiOpType.collection_delete_many); - DEPRECATED_OP_TYPES.put(DataApiOpType.delete_many, DataApiOpType.collection_delete_many); - DEPRECATED_OP_TYPES.put(DataApiOpType.delete_one, DataApiOpType.collection_delete_one); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_delete, DataApiOpType.collection_find_one_and_delete); - DEPRECATED_OP_TYPES.put(DataApiOpType.find, DataApiOpType.collection_find); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector, DataApiOpType.collection_find); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector_filter, DataApiOpType.collection_find); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_by_id, DataApiOpType.collection_find_one); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); // not a Data API primitive, it's client-emulated - DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); - DEPRECATED_OP_TYPES.put(DataApiOpType.update_one, DataApiOpType.collection_update_one); - DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); - DEPRECATED_OP_TYPES.put(DataApiOpType.replace_one, null); // not a Data API primitive, it's client-emulated - DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_replace, DataApiOpType.collection_find_one_and_replace); - DEPRECATED_OP_TYPES.put(DataApiOpType.update_many, DataApiOpType.collection_update_many); - DEPRECATED_OP_TYPES.put(DataApiOpType.count_documents, DataApiOpType.collection_count_documents); - DEPRECATED_OP_TYPES.put(DataApiOpType.estimated_document_count, DataApiOpType.collection_estimated_document_count); + DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one, DataApiOpType.collection_insert_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.insert_one_vector, DataApiOpType.collection_insert_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.insert_many, DataApiOpType.collection_insert_many); + DEPRECATED_OP_TYPES.put(DataApiOpType.delete_all, DataApiOpType.collection_delete_many); + DEPRECATED_OP_TYPES.put(DataApiOpType.delete_many, DataApiOpType.collection_delete_many); + DEPRECATED_OP_TYPES.put(DataApiOpType.delete_one, DataApiOpType.collection_delete_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_delete, DataApiOpType.collection_find_one_and_delete); + DEPRECATED_OP_TYPES.put(DataApiOpType.find, DataApiOpType.collection_find); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector, DataApiOpType.collection_find); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_vector_filter, DataApiOpType.collection_find); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_by_id, DataApiOpType.collection_find_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_distinct, null); // not a Data API primitive, it's client-emulated + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one, DataApiOpType.collection_find_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.update_one, DataApiOpType.collection_update_one); + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_update, DataApiOpType.collection_find_one_and_update); + DEPRECATED_OP_TYPES.put(DataApiOpType.replace_one, null); // not a Data API primitive, it's client-emulated + DEPRECATED_OP_TYPES.put(DataApiOpType.find_one_and_replace, DataApiOpType.collection_find_one_and_replace); + DEPRECATED_OP_TYPES.put(DataApiOpType.update_many, DataApiOpType.collection_update_many); + DEPRECATED_OP_TYPES.put(DataApiOpType.count_documents, DataApiOpType.collection_count_documents); + DEPRECATED_OP_TYPES.put(DataApiOpType.estimated_document_count, DataApiOpType.collection_estimated_document_count); } private final DataApiDriverAdapter adapter; @@ -103,7 +104,6 @@ public class DataApiOpMapper implements OpMapper { case list_namespaces -> new DataApiListNamespacesOpDispenser(adapter, op, typeAndTarget.targetFunction); case drop_namespace -> new DataApiDropNamespaceOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-database ops: - case create_collection -> new DataApiCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); case delete_collection -> new DataApiDropCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collections -> new DataApiListCollectionsOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collection_names -> @@ -113,6 +113,7 @@ public class DataApiOpMapper implements OpMapper { // admin ops: // db-admin ops: // in-database ops: + case create_collection -> new DataApiLegacyCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); case create_collection_with_class -> new DataApiLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -138,6 +139,8 @@ public class DataApiOpMapper implements OpMapper { new DataApiCollectionEstimatedDocumentCountOpDispenser(adapter, op, typeAndTarget.targetFunction); // NEW-STYLE OPS + // in-database ops: + case db_create_collection -> new DataApiDbCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case collection_insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbCreateCollectionOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbCreateCollectionOpDispenser.java new file mode 100644 index 000000000..1e61fafc3 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbCreateCollectionOpDispenser.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiDbCreateCollectionOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiDbCreateCollectionOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiDbCreateCollectionOpDispenser.class); + private final LongFunction opFunction; + + public DataApiDbCreateCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + DataApiDbCreateCollectionOp dataApiDbCreateCollectionOp = + new DataApiDbCreateCollectionOp( + spaceFunction.apply(l).getDatabase(), + targetFunction.apply(l), + this.getCollectionDefinitionFromOp(op, l) + ); + + return dataApiDbCreateCollectionOp; + }; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } + + +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionOpDispenser.java similarity index 70% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionOpDispenser.java index 7c4006781..d781cc9fe 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionOpDispenser.java @@ -18,27 +18,26 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiCreateCollectionOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiLegacyCreateCollectionOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.util.Optional; import java.util.function.LongFunction; -public class DataApiCreateCollectionOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiCreateCollectionOpDispenser.class); - private final LongFunction opFunction; +public class DataApiLegacyCreateCollectionOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiLegacyCreateCollectionOpDispenser.class); + private final LongFunction opFunction; - public DataApiCreateCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + public DataApiLegacyCreateCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { + private LongFunction createOpFunction(ParsedOp op) { return (l) -> { - DataApiCreateCollectionOp dataApiCreateCollectionOp = - new DataApiCreateCollectionOp( + DataApiLegacyCreateCollectionOp dataApiCreateCollectionOp = + new DataApiLegacyCreateCollectionOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), this.getLegacyCollectionDefinitionFromOp(op, l) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index c646f10a0..f3c86de5c 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -145,16 +145,9 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser update.set(field, value); - case "inc" -> update.inc(field, ((Number) value).doubleValue()); - case "unset" -> update.unset(field); - case "addToSet" -> update.addToSet(field, value); - case "min" -> update.min(field, ((Number) value).doubleValue()); - case "rename" -> update.rename(field, value.toString()); - default -> logger.error(() -> "Operation '" + operation + "' not supported"); - } + protected Map getCollectionDefinitionFromOp(ParsedOp op, long l) { + Map definition = getFreeFormFromOp(op, l, "definition", true); + return definition; } protected float[] getVectorValues(ParsedOp op, long l) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbCreateCollectionOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbCreateCollectionOp.java new file mode 100644 index 000000000..1039562f8 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbCreateCollectionOp.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.ops; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.collections.definition.documents.Document; +import com.datastax.astra.client.core.commands.Command; + +import java.util.Map; + +public class DataApiDbCreateCollectionOp extends DataApiBaseOp { + private final String collectionName; + private final Map definition; + + public DataApiDbCreateCollectionOp(Database db, String collectionName, Map definition) { + super(db); + this.collectionName = collectionName; + this.definition = definition; + } + + @Override + public Object apply(long value) { + Document ccPayload = new Document(); + ccPayload.append("name", collectionName); + ccPayload.append("options", definition); + Command ccCommand = new Command("createCollection", ccPayload); + return db.runCommand(ccCommand); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCreateCollectionOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyCreateCollectionOp.java similarity index 85% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCreateCollectionOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyCreateCollectionOp.java index ef01b4618..6f1ee2a8e 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCreateCollectionOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyCreateCollectionOp.java @@ -19,11 +19,11 @@ package io.nosqlbench.adapter.dataapi.ops; import com.datastax.astra.client.databases.Database; import com.datastax.astra.client.collections.definition.CollectionDefinition; -public class DataApiCreateCollectionOp extends DataApiBaseOp { +public class DataApiLegacyCreateCollectionOp extends DataApiBaseOp { private final String collectionName; private final CollectionDefinition definition; - public DataApiCreateCollectionOp(Database db, String collectionName, CollectionDefinition definition) { + public DataApiLegacyCreateCollectionOp(Database db, String collectionName, CollectionDefinition definition) { super(db); this.collectionName = collectionName; this.definition = definition; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 010fa93f2..9e3cc4870 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -29,7 +29,6 @@ public enum DataApiOpType { list_namespaces, drop_namespace, // in-database ops: - create_collection, delete_collection, list_collections, list_collection_names, @@ -38,6 +37,7 @@ public enum DataApiOpType { // admin ops: // db-admin ops: // in-database ops: + create_collection, create_collection_with_class, // in-collection ops: insert_one, @@ -65,6 +65,7 @@ public enum DataApiOpType { // admin ops: // db-admin ops: // in-database ops: + db_create_collection, // in-collection ops: collection_insert_one, collection_insert_many, From 710f0e6a85c776488e10fc9df86d190a53354316 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 22 Sep 2026 18:02:56 +0200 Subject: [PATCH 38/46] delete_collection, new and legacy --- .../adapter/dataapi/DataApiOpMapper.java | 4 +- ...DataApiDbDeleteCollectionOpDispenser.java} | 14 +++--- ...aApiLegacyDeleteCollectionOpDispenser.java | 47 +++++++++++++++++++ ....java => DataApiDbDeleteCollectionOp.java} | 4 +- .../ops/DataApiLegacyDeleteCollectionOp.java | 33 +++++++++++++ .../adapter/dataapi/ops/DataApiOpType.java | 3 +- 6 files changed, 94 insertions(+), 11 deletions(-) rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/{DataApiDropCollectionOpDispenser.java => DataApiDbDeleteCollectionOpDispenser.java} (70%) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyDeleteCollectionOpDispenser.java rename nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/{DataApiDropCollectionOp.java => DataApiDbDeleteCollectionOp.java} (90%) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyDeleteCollectionOp.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index 55c2b6cc3..bfb24815f 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -40,6 +40,7 @@ public class DataApiOpMapper implements OpMapper { // admin ops: DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection_with_class, DataApiOpType.db_create_collection); DEPRECATED_OP_TYPES.put(DataApiOpType.create_collection, DataApiOpType.db_create_collection); + DEPRECATED_OP_TYPES.put(DataApiOpType.delete_collection, DataApiOpType.db_delete_collection); // db-admin ops: // in-database ops: // in-collection ops: @@ -104,7 +105,6 @@ public class DataApiOpMapper implements OpMapper { case list_namespaces -> new DataApiListNamespacesOpDispenser(adapter, op, typeAndTarget.targetFunction); case drop_namespace -> new DataApiDropNamespaceOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-database ops: - case delete_collection -> new DataApiDropCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collections -> new DataApiListCollectionsOpDispenser(adapter, op, typeAndTarget.targetFunction); case list_collection_names -> new DataApiListCollectionNamesOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -115,6 +115,7 @@ public class DataApiOpMapper implements OpMapper { // in-database ops: case create_collection -> new DataApiLegacyCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); case create_collection_with_class -> new DataApiLegacyCreateCollectionWithClassOpDispenser(adapter, op, typeAndTarget.targetFunction); + case delete_collection -> new DataApiLegacyDeleteCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case insert_one_vector -> new DataApiCollectionLegacyInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction); @@ -141,6 +142,7 @@ public class DataApiOpMapper implements OpMapper { // NEW-STYLE OPS // in-database ops: case db_create_collection -> new DataApiDbCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); + case db_delete_collection -> new DataApiDbDeleteCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction); // in-collection ops: case collection_insert_one -> new DataApiCollectionInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDropCollectionOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbDeleteCollectionOpDispenser.java similarity index 70% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDropCollectionOpDispenser.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbDeleteCollectionOpDispenser.java index 15caa8afc..701197d42 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDropCollectionOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDbDeleteCollectionOpDispenser.java @@ -18,23 +18,23 @@ package io.nosqlbench.adapter.dataapi.opdispensers; import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; -import io.nosqlbench.adapter.dataapi.ops.DataApiDropCollectionOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiLegacyDeleteCollectionOp; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.function.LongFunction; -public class DataApiDropCollectionOpDispenser extends DataApiOpDispenser { - private static final Logger logger = LogManager.getLogger(DataApiDropCollectionOpDispenser.class); - private final LongFunction opFunction; - public DataApiDropCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { +public class DataApiDbDeleteCollectionOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiDbDeleteCollectionOpDispenser.class); + private final LongFunction opFunction; + public DataApiDbDeleteCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { super(adapter, op, targetFunction); this.opFunction = createOpFunction(op); } - private LongFunction createOpFunction(ParsedOp op) { - return (l) -> new DataApiDropCollectionOp( + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> new DataApiLegacyDeleteCollectionOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l) ); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyDeleteCollectionOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyDeleteCollectionOpDispenser.java new file mode 100644 index 000000000..65c933f32 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyDeleteCollectionOpDispenser.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiLegacyDeleteCollectionOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; + +public class DataApiLegacyDeleteCollectionOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiLegacyDeleteCollectionOpDispenser.class); + private final LongFunction opFunction; + public DataApiLegacyDeleteCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> new DataApiLegacyDeleteCollectionOp( + spaceFunction.apply(l).getDatabase(), + targetFunction.apply(l) + ); + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDropCollectionOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbDeleteCollectionOp.java similarity index 90% rename from nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDropCollectionOp.java rename to nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbDeleteCollectionOp.java index feb5e406e..e3aabd52f 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDropCollectionOp.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiDbDeleteCollectionOp.java @@ -18,9 +18,9 @@ package io.nosqlbench.adapter.dataapi.ops; import com.datastax.astra.client.databases.Database; -public class DataApiDropCollectionOp extends DataApiBaseOp { +public class DataApiDbDeleteCollectionOp extends DataApiBaseOp { private final String collectionName; - public DataApiDropCollectionOp(Database db, String collectionName) { + public DataApiDbDeleteCollectionOp(Database db, String collectionName) { super(db); this.collectionName = collectionName; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyDeleteCollectionOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyDeleteCollectionOp.java new file mode 100644 index 000000000..380a2403b --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiLegacyDeleteCollectionOp.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.ops; + +import com.datastax.astra.client.databases.Database; + +public class DataApiLegacyDeleteCollectionOp extends DataApiBaseOp { + private final String collectionName; + public DataApiLegacyDeleteCollectionOp(Database db, String collectionName) { + super(db); + this.collectionName = collectionName; + } + + @Override + public Object apply(long value) { + db.dropCollection(collectionName); + return null; + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index 9e3cc4870..b31134863 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -29,7 +29,6 @@ public enum DataApiOpType { list_namespaces, drop_namespace, // in-database ops: - delete_collection, list_collections, list_collection_names, @@ -39,6 +38,7 @@ public enum DataApiOpType { // in-database ops: create_collection, create_collection_with_class, + delete_collection, // in-collection ops: insert_one, insert_one_vector, @@ -66,6 +66,7 @@ public enum DataApiOpType { // db-admin ops: // in-database ops: db_create_collection, + db_delete_collection, // in-collection ops: collection_insert_one, collection_insert_many, From 868bb4630d5a46c3e1aef65a4dddddd334664a2f Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Tue, 22 Sep 2026 23:42:25 +0200 Subject: [PATCH 39/46] data api: new findAndRerank op --- .../adapter/dataapi/DataApiOpMapper.java | 1 + ...ApiCollectionFindAndRerankOpDispenser.java | 117 +++++++++++++++ .../DataApiCollectionFindOpDispenser.java | 4 + .../opdispensers/DataApiOpDispenser.java | 136 +++++++++++++++++- .../ops/DataApiCollectionFindAndRerankOp.java | 43 ++++++ .../adapter/dataapi/ops/DataApiOpType.java | 1 + 6 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindAndRerankOpDispenser.java create mode 100644 nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindAndRerankOp.java diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java index bfb24815f..306e76d05 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java @@ -148,6 +148,7 @@ public class DataApiOpMapper implements OpMapper { case collection_insert_many -> new DataApiCollectionInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find -> new DataApiCollectionFindOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one -> new DataApiCollectionFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction); + case collection_find_and_rerank -> new DataApiCollectionFindAndRerankOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_update_one -> new DataApiCollectionUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_find_one_and_update -> new DataApiCollectionFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction); case collection_delete_many -> new DataApiCollectionDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindAndRerankOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindAndRerankOpDispenser.java new file mode 100644 index 000000000..f4761c7c1 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindAndRerankOpDispenser.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.opdispensers; + +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.collections.commands.options.CollectionFindAndRerankOptions; +import com.datastax.astra.client.core.query.Sort; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.core.query.Projection; +import com.datastax.astra.client.core.rerank.RerankServiceOptions; +import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter; +import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp; +import io.nosqlbench.adapter.dataapi.ops.DataApiCollectionFindAndRerankOp; +import io.nosqlbench.adapters.api.templating.ParsedOp; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.function.LongFunction; +import java.util.Map; +import java.util.Optional; + +public class DataApiCollectionFindAndRerankOpDispenser extends DataApiOpDispenser { + private static final Logger logger = LogManager.getLogger(DataApiCollectionFindAndRerankOpDispenser.class); + private final LongFunction opFunction; + + public DataApiCollectionFindAndRerankOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) { + super(adapter, op, targetFunction); + this.opFunction = createOpFunction(op); + } + + private LongFunction createOpFunction(ParsedOp op) { + return (l) -> { + Database db = spaceFunction.apply(l).getDatabase(); + Filter filter = getFilterFromOp(op, l); + CollectionFindAndRerankOptions options = getCollectionFindAndRerankOptions(op, l); + + return new DataApiCollectionFindAndRerankOp( + db, + db.getCollection(targetFunction.apply(l)), + filter, + options + ); + }; + } + + private CollectionFindAndRerankOptions getCollectionFindAndRerankOptions(ParsedOp op, long l) { + CollectionFindAndRerankOptions options = new CollectionFindAndRerankOptions(); + Sort sort = getFindAndRerankSortFromOp(op, l); + options = options.sort(sort); + Projection[] projection = getProjectionFromOp(op, l); + if (projection != null) { + options = options.projection(projection); + } + Optional limit = getLimitFromOp(op, l); + if (limit.isPresent()) { + options = options.limit(limit.get()); + } + Optional includeSortVector = getIncludeSortVectorFromOp(op, l); + if (includeSortVector.isPresent()) { + options = options.includeSortVector(includeSortVector.get()); + } + Optional includeScores = getIncludeScoresFromOp(op, l); + if (includeScores.isPresent()) { + options = options.includeScores(includeScores.get()); + } + Optional rerankQuery = getRerankQueryFromOp(op, l); + if (rerankQuery.isPresent()) { + options = options.rerankQuery(rerankQuery.get()); + } + Optional rerankOn = getRerankOnFromOp(op, l); + if (rerankOn.isPresent()) { + options = options.rerankOn(rerankOn.get()); + } + Optional hybridLimits = getHybridLimitsFromOp(op, l); + if (hybridLimits.isPresent()) { + Object hl = hybridLimits.get(); + if (hl instanceof Integer i) { + options = options.hybridLimits(i); + } else { + @SuppressWarnings("unchecked") + Map hlMap = (Map) hl; + options = options.hybridLimits(hlMap); + } + } + Optional rerankService = getRerankServiceFromOp(op, l); + if (rerankService.isPresent()) { + options = options.rerankService(rerankService.get()); + } + // TEMP + RerankServiceOptions rop = new RerankServiceOptions(); + rop.provider("providerZ"); + rop.modelName("modelNameZ"); + options = options.rerankService(rop); + // END TEMP + + return options; + } + + @Override + public DataApiBaseOp getOp(long cycle) { + return opFunction.apply(cycle); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java index f3429c86f..ed81f28a7 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java @@ -71,6 +71,10 @@ public class DataApiCollectionFindOpDispenser extends DataApiOpDispenser { if (skip.isPresent()) { options = options.skip(skip.get()); } + Optional includeSortVector = getIncludeSortVectorFromOp(op, l); + if (includeSortVector.isPresent()) { + options = options.includeSortVector(includeSortVector.get()); + } Optional includeSimilarity = getIncludeSimilarityFromOp(op, l); if (includeSimilarity.isPresent()) { options.includeSimilarity(includeSimilarity.get()); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index f3c86de5c..d6c37c792 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -24,7 +24,9 @@ import com.datastax.astra.client.collections.definition.documents.Document; import com.datastax.astra.client.collections.commands.ReturnDocument; import com.datastax.astra.client.collections.commands.Update; import com.datastax.astra.client.collections.commands.Updates; +import com.datastax.astra.client.core.hybrid.Hybrid; import com.datastax.astra.client.core.query.Sort; +import com.datastax.astra.client.core.rerank.RerankServiceOptions; import com.datastax.astra.client.core.vector.SimilarityMetric; import com.datastax.astra.client.core.query.Projection; import io.nosqlbench.adapter.dataapi.DataApiSpace; @@ -251,8 +253,17 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser getIncludeSimilarityFromOp(ParsedOp op, long l) { Optional> includeSimFunction = op.getAsOptionalFunction("include_similarity", Boolean.class); if (includeSimFunction.isPresent()) { - LongFunction uf = includeSimFunction.get(); - return Optional.of(uf.apply(l)); + LongFunction sf = includeSimFunction.get(); + return Optional.of(sf.apply(l)); + } + return Optional.empty(); + } + + protected Optional getIncludeSortVectorFromOp(ParsedOp op, long l) { + Optional> includeSvFunction = op.getAsOptionalFunction("include_sort_vector", Boolean.class); + if (includeSvFunction.isPresent()) { + LongFunction sv = includeSvFunction.get(); + return Optional.of(sv.apply(l)); } return Optional.empty(); } @@ -307,6 +318,127 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser getIncludeScoresFromOp(ParsedOp op, long l) { + Optional> includeScFunction = op.getAsOptionalFunction("include_scores", Boolean.class); + if (includeScFunction.isPresent()) { + LongFunction isf = includeScFunction.get(); + return Optional.of(isf.apply(l)); + } + return Optional.empty(); + } + + protected Optional getRerankQueryFromOp(ParsedOp op, long l) { + Optional> rqf = op.getAsOptionalFunction("rerank_query", String.class); + if (rqf.isPresent()) { + String rqValue = rqf.get().apply(l); + return Optional.of(rqValue); + } + return Optional.empty(); + } + + protected Optional getRerankOnFromOp(ParsedOp op, long l) { + Optional> rof = op.getAsOptionalFunction("rerank_on", String.class); + if (rof.isPresent()) { + String roValue = rof.get().apply(l); + return Optional.of(roValue); + } + return Optional.empty(); + } + + @SuppressWarnings("unchecked") + protected Optional getHybridLimitsFromOp(ParsedOp op, long l) { + Optional> hlFunc = op.getAsOptionalFunction("hybrid_limits", Object.class); + if (hlFunc.isPresent()) { + Object hlValue = hlFunc.get().apply(l); + if (hlValue instanceof Integer || hlValue instanceof Long) { + return Optional.of(hlValue); + } else if (hlValue instanceof Map rawMap) { + return Optional.of((Map) rawMap); + } else { + throw new OpConfigError( + "'hybrid_limits' must be an integer or a map, got: " + hlValue.getClass().getSimpleName() + ); + } + } + return Optional.empty(); + } + + protected Optional getRerankServiceFromOp(ParsedOp op, long l) { + Map rerankService = getFreeFormFromOp(op, l, "rerank", false); + if (rerankService != null) { + RerankServiceOptions rsOptions = new RerankServiceOptions(); + if (rerankService.containsKey("provider")) { + rsOptions = rsOptions.provider((String) rerankService.get("provider")); + } + if (rerankService.containsKey("modelName")) { + rsOptions = rsOptions.modelName((String) rerankService.get("modelName")); + } + if (rerankService.containsKey("authentication")) { + rsOptions = rsOptions.authentication((Map) rerankService.get("authentication")); + } + if (rerankService.containsKey("parameters")) { + rsOptions = rsOptions.parameters((Map) rerankService.get("parameters")); + } + return Optional.of(rsOptions); + } + return Optional.empty(); + } + + protected Sort getFindAndRerankSortFromOp(ParsedOp op, long l) { + Map docMap = getFreeFormFromOp(op, l, "sort", true); + + if (docMap.size() != 1 || !docMap.containsKey("$hybrid")) { + throw new OpConfigError("'sort' must contain exactly one key: '$hybrid'"); + } + + Object hybridValue = docMap.get("$hybrid"); + + if (hybridValue instanceof String hybridString) { + return Sort.hybrid(hybridString); + } + + if (hybridValue instanceof Map rawMap) { + @SuppressWarnings("unchecked") + Map hybMap = (Map) rawMap; + + boolean hasVectorize = hybMap.containsKey("$vectorize"); + boolean hasVector = hybMap.containsKey("$vector"); + if (!hasVectorize && !hasVector) { + throw new OpConfigError( + "'$hybrid' sub-object must contain at least one of '$vectorize' or '$vector'" + ); + } + + Set allowedKeys = Set.of("$vectorize", "$vector", "$lexical"); + for (String key : hybMap.keySet()) { + if (!allowedKeys.contains(key)) { + throw new OpConfigError("Unexpected key in '$hybrid' sub-object: '" + key + "'"); + } + } + + Hybrid hyb = new Hybrid(); + if (hasVectorize) { + hyb = hyb.vectorize((String) hybMap.get("$vectorize")); + } + if (hasVector) { + @SuppressWarnings("unchecked") + List vectorList = (List) hybMap.get("$vector"); + float[] vectorArray = new float[vectorList.size()]; + int i = 0; + for (Number n : vectorList) vectorArray[i++] = n.floatValue(); + hyb = hyb.vector(vectorArray); + } + if (hybMap.containsKey("$lexical")) { + hyb = hyb.lexical((String) hybMap.get("$lexical")); + } + return Sort.hybrid(hyb); + } + + throw new OpConfigError( + "'$hybrid' value must be a string or a sub-object, got: " + hybridValue.getClass().getSimpleName() + ); + } + /* LEGACY OP DISPENSER UTILS START HERE */ /* diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindAndRerankOp.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindAndRerankOp.java new file mode 100644 index 000000000..2f22964b4 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiCollectionFindAndRerankOp.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) nosqlbench + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.nosqlbench.adapter.dataapi.ops; + +import com.datastax.astra.client.collections.Collection; +import com.datastax.astra.client.databases.Database; +import com.datastax.astra.client.core.query.Filter; +import com.datastax.astra.client.collections.definition.documents.Document; +import com.datastax.astra.client.collections.commands.cursor.CollectionFindAndRerankCursor; +import com.datastax.astra.client.collections.commands.options.CollectionFindAndRerankOptions; + +public class DataApiCollectionFindAndRerankOp extends DataApiBaseOp { + private final Collection collection; + private final Filter filter; + private final CollectionFindAndRerankOptions options; + + public DataApiCollectionFindAndRerankOp(Database db, Collection collection, Filter filter, CollectionFindAndRerankOptions options) { + super(db); + this.collection = collection; + this.filter = filter; + this.options = options; + } + + @Override + public Object apply(long value) { + CollectionFindAndRerankCursor cursor = collection.findAndRerank(filter, options); + return cursor.toList(); + } +} diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java index b31134863..46a073a2e 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/ops/DataApiOpType.java @@ -75,6 +75,7 @@ public enum DataApiOpType { collection_find_one_and_delete, collection_find, collection_find_one, + collection_find_and_rerank, collection_update_one, collection_find_one_and_update, collection_find_one_and_replace, From e6adad0016ed9e84349297854fa2b73aaeb46b97 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Wed, 23 Sep 2026 23:54:37 +0200 Subject: [PATCH 40/46] uniform handling of vectors: list/comma-string/bindings, always bin-encoded in payloads - for all commands --- ...ectionLegacyCountDocumentsOpDispenser.java | 2 +- ...CollectionLegacyDeleteManyOpDispenser.java | 2 +- ...iCollectionLegacyDeleteOneOpDispenser.java | 2 +- ...llectionLegacyFindDistinctOpDispenser.java | 2 +- ...tionLegacyFindOneAndDeleteOpDispenser.java | 2 +- ...ionLegacyFindOneAndReplaceOpDispenser.java | 2 +- ...tionLegacyFindOneAndUpdateOpDispenser.java | 4 +- ...ApiCollectionLegacyFindOneOpDispenser.java | 2 +- ...ataApiCollectionLegacyFindOpDispenser.java | 2 +- ...tionLegacyFindVectorFilterOpDispenser.java | 2 +- ...CollectionLegacyReplaceOneOpDispenser.java | 2 +- ...CollectionLegacyUpdateManyOpDispenser.java | 2 +- ...iCollectionLegacyUpdateOneOpDispenser.java | 2 +- ...aApiLegacyCreateCollectionOpDispenser.java | 2 +- ...yCreateCollectionWithClassOpDispenser.java | 2 +- .../opdispensers/DataApiOpDispenser.java | 96 ++++++++++--------- 16 files changed, 67 insertions(+), 61 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java index fa4a99c45..667b407ac 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyCountDocumentsOpDispenser.java @@ -39,7 +39,7 @@ public class DataApiCollectionLegacyCountDocumentsOpDispenser extends DataApiOpD private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); int upperBound = op.getAsRequiredFunction("upperbound", Integer.class).apply(l); return new DataApiCollectionLegacyCountDocumentsOp( diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java index c3ec617b9..29d28a6a6 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteManyOpDispenser.java @@ -39,7 +39,7 @@ public class DataApiCollectionLegacyDeleteManyOpDispenser extends DataApiOpDispe private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); return new DataApiCollectionDeleteManyOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java index 9356b23ee..13d0311f9 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java @@ -41,7 +41,7 @@ public class DataApiCollectionLegacyDeleteOneOpDispenser extends DataApiOpDispen private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionDeleteOneOptions options = getCollectionDeleteOneOptions(op, l); return new DataApiCollectionDeleteOneOp( diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java index c1e8ba263..38e6701e0 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindDistinctOpDispenser.java @@ -39,7 +39,7 @@ public class DataApiCollectionLegacyFindDistinctOpDispenser extends DataApiOpDis private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); Class targetClass = getTargetClass(op, l); return new DataApiCollectionLegacyFindDistinctOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java index 6c9fa9d2a..d453eb173 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java @@ -42,7 +42,7 @@ public class DataApiCollectionLegacyFindOneAndDeleteOpDispenser extends DataApiO private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionFindOneAndDeleteOptions options = getCollectionFindOneAndDeleteOptions(op, l); return new DataApiCollectionFindOneAndDeleteOp( diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java index 970c274ed..47f878130 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java @@ -46,7 +46,7 @@ public class DataApiCollectionLegacyFindOneAndReplaceOpDispenser extends DataApi private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionFindOneAndReplaceOptions options = getCollectionFindOneAndReplaceOptions(op, l); LongFunction docMapFunc = op.getAsRequiredFunction("document", Map.class); LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java index 6388b4540..b6cdd1298 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java @@ -42,8 +42,8 @@ public class DataApiCollectionLegacyFindOneAndUpdateOpDispenser extends DataApiO private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); - Update update = getLegacyUpdateFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); + Update update = legacyGetUpdateFromOp(op, l); CollectionFindOneAndUpdateOptions options = getCollectionLegacyFindOneAndUpdateOptions(op, l); return new DataApiCollectionLegacyFindOneAndUpdateOp( diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java index ff881a81d..e7d6fb288 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java @@ -42,7 +42,7 @@ public class DataApiCollectionLegacyFindOneOpDispenser extends DataApiOpDispense private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionFindOneOptions options = getCollectionFindOneOptions(op, l); return new DataApiCollectionFindOneOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java index e617dc69f..df23f177e 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java @@ -42,7 +42,7 @@ public class DataApiCollectionLegacyFindOpDispenser extends DataApiOpDispenser { private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionFindOptions options = getCollectionFindOptions(op, l); return new DataApiCollectionFindOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorFilterOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorFilterOpDispenser.java index e6cad50df..6e4945475 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorFilterOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindVectorFilterOpDispenser.java @@ -39,7 +39,7 @@ public class DataApiCollectionLegacyFindVectorFilterOpDispenser extends DataApiO return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); float[] vector = getVectorValues(op, l); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); int limit = getLimit(op, l); return new DataApiCollectionLegacyFindVectorFilterOp( db, diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java index ff5f2a07f..452ac5dd2 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java @@ -46,7 +46,7 @@ public class DataApiCollectionLegacyReplaceOneOpDispenser extends DataApiOpDispe private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionReplaceOneOptions options = getCollectionReplaceOneOptions(op, l); LongFunction docMapFunc = op.getAsRequiredFunction("document", Map.class); LongFunction docFunc = (long m) -> new Document(docMapFunc.apply(m)); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java index 6cfe17396..9a96daa8e 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateManyOpDispenser.java @@ -43,7 +43,7 @@ public class DataApiCollectionLegacyUpdateManyOpDispenser extends DataApiOpDispe private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionUpdateManyOptions options = getCollectionUpdateManyOptions(op, l); LongFunction docMapFunc = op.getAsRequiredFunction("updates", Map.class); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java index dc9fdbf3c..f9f4e3b81 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java @@ -44,7 +44,7 @@ public class DataApiCollectionLegacyUpdateOneOpDispenser extends DataApiOpDispen private LongFunction createOpFunction(ParsedOp op) { return (l) -> { Database db = spaceFunction.apply(l).getDatabase(); - Filter filter = getLegacyFilterFromOp(op, l); + Filter filter = legacyGetFilterFromOp(op, l); CollectionUpdateOneOptions options = getCollectionUpdateOneOptions(op, l); LongFunction docMapFunc = op.getAsRequiredFunction("update", Map.class); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionOpDispenser.java index d781cc9fe..f3bbab85a 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionOpDispenser.java @@ -40,7 +40,7 @@ public class DataApiLegacyCreateCollectionOpDispenser extends DataApiOpDispenser new DataApiLegacyCreateCollectionOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), - this.getLegacyCollectionDefinitionFromOp(op, l) + this.legacyGetCollectionDefinitionFromOp(op, l) ); return dataApiCreateCollectionOp; diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionWithClassOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionWithClassOpDispenser.java index 1d7f2289a..0f5f3a464 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionWithClassOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiLegacyCreateCollectionWithClassOpDispenser.java @@ -38,7 +38,7 @@ public class DataApiLegacyCreateCollectionWithClassOpDispenser extends DataApiOp return (l) -> new DataApiLegacyCreateCollectionWithClassOp( spaceFunction.apply(l).getDatabase(), targetFunction.apply(l), - this.getLegacyCollectionDefinitionFromOp(op, l), + this.legacyGetCollectionDefinitionFromOp(op, l), getCreateClass(op, l) ); } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index d6c37c792..653d1bfdd 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -27,6 +27,7 @@ import com.datastax.astra.client.collections.commands.Updates; import com.datastax.astra.client.core.hybrid.Hybrid; import com.datastax.astra.client.core.query.Sort; import com.datastax.astra.client.core.rerank.RerankServiceOptions; +import com.datastax.astra.client.core.vector.DataAPIVector; import com.datastax.astra.client.core.vector.SimilarityMetric; import com.datastax.astra.client.core.query.Projection; import io.nosqlbench.adapter.dataapi.DataApiSpace; @@ -69,6 +70,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser docMap) { + Document doc = new Document(docMap); + // if docMap has a '$vector' key, invoke: + if (docMap.containsKey("$vector")) { + doc.vector(new DataAPIVector(getVectorValues(docMap.get("$vector")))); + } + return doc; + } + protected Document getDocumentFromOp(ParsedOp op, long l) { Map docMap = getFreeFormFromOp(op, l, "document", true); - return new Document(docMap); + return getDocumentFromRawMap(docMap); } protected List getDocumentsFromOp(ParsedOp op, long l) { List> docMapList = getFreeFormListFromOp(op, l, "documents", true); - return docMapList.stream().map(Document::new).toList(); - } - - protected void addOperatorFilter(List filtersList, String operator, String fieldName, Object fieldValue) { - switch (operator) { - case "all" -> - filtersList.add(Filters.all(fieldName, fieldValue)); - case "eq" -> - filtersList.add(Filters.eq(fieldName, fieldValue)); - case "exists" -> { - if (fieldValue != null) { - logger.warn(() -> "'exists' operator does not support value field"); - } - filtersList.add(Filters.exists(fieldName)); - } - case "gt" -> - filtersList.add(Filters.gt(fieldName, ((Number) fieldValue).longValue())); - case "gte" -> - filtersList.add(Filters.gte(fieldName, ((Number) fieldValue).longValue())); - case "hasSize" -> - filtersList.add(Filters.hasSize(fieldName, ((Number) fieldValue).intValue())); - case "in" -> - filtersList.add(Filters.in(fieldName, fieldValue)); - case "lt" -> - filtersList.add(Filters.lt(fieldName, ((Number) fieldValue).longValue())); - case "lte" -> - filtersList.add(Filters.lte(fieldName, ((Number) fieldValue).longValue())); - case "ne" -> - filtersList.add(Filters.ne(fieldName, fieldValue)); - case "nin" -> - filtersList.add(Filters.nin(fieldName, fieldValue)); - default -> logger.error(() -> "Operation '" + operator + "' not supported"); - } + return docMapList.stream().map((docMap) -> getDocumentFromRawMap(docMap)).toList(); } protected Update getUpdateFromOp(ParsedOp op, long l) { @@ -421,12 +400,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser vectorList = (List) hybMap.get("$vector"); - float[] vectorArray = new float[vectorList.size()]; - int i = 0; - for (Number n : vectorList) vectorArray[i++] = n.floatValue(); - hyb = hyb.vector(vectorArray); + hyb = hyb.vector(new DataAPIVector(getVectorValues(hybMap.get("$vector")))); } if (hybMap.containsKey("$lexical")) { hyb = hyb.lexical((String) hybMap.get("$lexical")); @@ -448,7 +422,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> updatesFunction = op.getAsOptionalFunction("updates", Map.class); if (updatesFunction.isPresent()) { @@ -480,6 +454,38 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser filtersList, String operator, String fieldName, Object fieldValue) { + switch (operator) { + case "all" -> + filtersList.add(Filters.all(fieldName, fieldValue)); + case "eq" -> + filtersList.add(Filters.eq(fieldName, fieldValue)); + case "exists" -> { + if (fieldValue != null) { + logger.warn(() -> "'exists' operator does not support value field"); + } + filtersList.add(Filters.exists(fieldName)); + } + case "gt" -> + filtersList.add(Filters.gt(fieldName, ((Number) fieldValue).longValue())); + case "gte" -> + filtersList.add(Filters.gte(fieldName, ((Number) fieldValue).longValue())); + case "hasSize" -> + filtersList.add(Filters.hasSize(fieldName, ((Number) fieldValue).intValue())); + case "in" -> + filtersList.add(Filters.in(fieldName, fieldValue)); + case "lt" -> + filtersList.add(Filters.lt(fieldName, ((Number) fieldValue).longValue())); + case "lte" -> + filtersList.add(Filters.lte(fieldName, ((Number) fieldValue).longValue())); + case "ne" -> + filtersList.add(Filters.ne(fieldName, fieldValue)); + case "nin" -> + filtersList.add(Filters.nin(fieldName, fieldValue)); + default -> logger.error(() -> "Operation '" + operator + "' not supported"); + } + } + /* filters: - conjunction: "and" @@ -491,7 +497,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> filterFunction = op.getAsOptionalFunction("filters", List.class) .or(() -> op.getAsOptionalFunction("filter",List.class)); @@ -504,9 +510,9 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser filterFields : filters) { switch ((String)filterFields.get("conjunction")) { case "and" -> - addOperatorFilter(andFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); + legacyAddOperatorFilter(andFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); case "or" -> - addOperatorFilter(orFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); + legacyAddOperatorFilter(orFilterList, filterFields.get("operator").toString(), filterFields.get("field").toString(), filterFields.get("value")); default -> logger.error(() -> "Conjunction " + filterFields.get("conjunction") + " not supported"); } } @@ -525,7 +531,7 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> dimFunc = op.getAsOptionalFunction("dimensions", Integer.class); if (dimFunc.isPresent()) { From aca86cdd7d7ce13e5f99d4a52c5961556f63b9a1 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 24 Sep 2026 11:30:07 +0200 Subject: [PATCH 41/46] add vectorize support to all sort clauses --- .../opdispensers/DataApiOpDispenser.java | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 653d1bfdd..3cc775575 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -53,7 +53,15 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser 1) { + throw new OpConfigError( + "Can sort by only one of: 'sort' (regular asc/desc), 'vector', 'vectorize' in an op." + ); + } + Optional> sortFunction = op.getAsOptionalFunction("sort", Map.class); if (sortFunction.isPresent()) { @SuppressWarnings("unchecked") @@ -61,32 +69,28 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser fieldSort = Sort.ascending(sortField); - case "desc" -> fieldSort = Sort.descending(sortField); + case "asc" -> sort = Sort.ascending(sortField); + case "desc" -> sort = Sort.descending(sortField); } } - Sort vectorSort = null; if (op.isDefined("vector")) { float[] vector = getVectorValues(op, l); if (vector != null) { // TODO use DataAPIVector as soon as the client allows here: - vectorSort = Sort.vector(vector); + sort = Sort.vector(vector); } } - if (fieldSort != null && vectorSort != null) { - throw new OpConfigError( - "cannot sort by vector and regular asc/desc criteria at the same time." - ); + if (op.isDefined("vectorize")) { + Optional> vzeFunction = op.getAsOptionalFunction("vectorize", String.class); + if (vzeFunction.isPresent()){ + String vectorize = vzeFunction.get().apply(l); + sort = Sort.vectorize(vectorize); + } } - if (vectorSort != null) { - return vectorSort; - } - if (fieldSort != null) { - return fieldSort; - } - return null; + + return sort; } protected Filter getFilterFromOp(ParsedOp op, long l) { From 8a3b2d60b1f7c0cedd34c2c35c7d1b2e1ed91278 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 24 Sep 2026 12:17:20 +0200 Subject: [PATCH 42/46] split legacyGetSortFromOp/getSortFromOp and reinstate legacy sort for legacy ops --- ...DataApiCollectionDeleteOneOpDispenser.java | 6 +- ...CollectionFindOneAndDeleteOpDispenser.java | 6 +- ...ollectionFindOneAndReplaceOpDispenser.java | 6 +- ...CollectionFindOneAndUpdateOpDispenser.java | 6 +- .../DataApiCollectionFindOneOpDispenser.java | 6 +- .../DataApiCollectionFindOpDispenser.java | 6 +- ...iCollectionLegacyDeleteOneOpDispenser.java | 6 +- ...tionLegacyFindOneAndDeleteOpDispenser.java | 6 +- ...ionLegacyFindOneAndReplaceOpDispenser.java | 6 +- ...tionLegacyFindOneAndUpdateOpDispenser.java | 6 +- ...ApiCollectionLegacyFindOneOpDispenser.java | 6 +- ...ataApiCollectionLegacyFindOpDispenser.java | 6 +- ...CollectionLegacyReplaceOneOpDispenser.java | 6 +- ...iCollectionLegacyUpdateOneOpDispenser.java | 7 +- ...DataApiCollectionUpdateOneOpDispenser.java | 6 +- .../opdispensers/DataApiOpDispenser.java | 86 ++++++++++++++++--- 16 files changed, 120 insertions(+), 57 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java index f0ee8c2be..98db0b751 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionDeleteOneOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionDeleteOneOpDispenser extends DataApiOpDispenser { private CollectionDeleteOneOptions getCollectionDeleteOneOptions(ParsedOp op, long l) { CollectionDeleteOneOptions options = new CollectionDeleteOneOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = getSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java index fd8fc11a5..17aba0f00 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndDeleteOpDispenser.java @@ -56,9 +56,9 @@ public class DataApiCollectionFindOneAndDeleteOpDispenser extends DataApiOpDispe private CollectionFindOneAndDeleteOptions getCollectionFindOneAndDeleteOptions(ParsedOp op, long l) { CollectionFindOneAndDeleteOptions options = new CollectionFindOneAndDeleteOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = getSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java index 3f81d59d7..a959baeee 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndReplaceOpDispenser.java @@ -60,9 +60,9 @@ public class DataApiCollectionFindOneAndReplaceOpDispenser extends DataApiOpDisp private CollectionFindOneAndReplaceOptions getCollectionFindOneAndReplaceOptions(ParsedOp op, long l) { CollectionFindOneAndReplaceOptions options = new CollectionFindOneAndReplaceOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = getSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java index 0c33f1faf..755b2f5a0 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneAndUpdateOpDispenser.java @@ -59,10 +59,10 @@ public class DataApiCollectionFindOneAndUpdateOpDispenser extends DataApiOpDispe private CollectionFindOneAndUpdateOptions getCollectionFindOneAndUpdateOptions(ParsedOp op, long l) { CollectionFindOneAndUpdateOptions options = new CollectionFindOneAndUpdateOptions(); - Sort sort = getSortFromOp(op, l); + Sort[] sorts = getSortFromOp(op, l); Boolean upsert = getUpsertFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + if (sorts != null) { + options = options.sort(sorts); } if ( upsert != null ){ options = options.upsert(upsert); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java index 6af0190cd..75553269c 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOneOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionFindOneOpDispenser extends DataApiOpDispenser { private CollectionFindOneOptions getCollectionFindOneOptions(ParsedOp op, long l) { CollectionFindOneOptions options = new CollectionFindOneOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = getSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java index ed81f28a7..602ff3de9 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionFindOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionFindOpDispenser extends DataApiOpDispenser { private CollectionFindOptions getCollectionFindOptions(ParsedOp op, long l) { CollectionFindOptions options = new CollectionFindOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = getSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java index 13d0311f9..58f49cd78 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyDeleteOneOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionLegacyDeleteOneOpDispenser extends DataApiOpDispen private CollectionDeleteOneOptions getCollectionDeleteOneOptions(ParsedOp op, long l) { CollectionDeleteOneOptions options = new CollectionDeleteOneOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = legacyGetSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } return options; } diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java index d453eb173..cf0c50ee5 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndDeleteOpDispenser.java @@ -56,9 +56,9 @@ public class DataApiCollectionLegacyFindOneAndDeleteOpDispenser extends DataApiO private CollectionFindOneAndDeleteOptions getCollectionFindOneAndDeleteOptions(ParsedOp op, long l) { CollectionFindOneAndDeleteOptions options = new CollectionFindOneAndDeleteOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = legacyGetSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java index 47f878130..d1869bf0c 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndReplaceOpDispenser.java @@ -63,9 +63,9 @@ public class DataApiCollectionLegacyFindOneAndReplaceOpDispenser extends DataApi private CollectionFindOneAndReplaceOptions getCollectionFindOneAndReplaceOptions(ParsedOp op, long l) { CollectionFindOneAndReplaceOptions options = new CollectionFindOneAndReplaceOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = legacyGetSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java index b6cdd1298..d3d2eb7ed 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneAndUpdateOpDispenser.java @@ -58,10 +58,10 @@ public class DataApiCollectionLegacyFindOneAndUpdateOpDispenser extends DataApiO private CollectionFindOneAndUpdateOptions getCollectionLegacyFindOneAndUpdateOptions(ParsedOp op, long l) { CollectionFindOneAndUpdateOptions options = new CollectionFindOneAndUpdateOptions(); - Sort sort = getSortFromOp(op, l); + Sort[] sorts = legacyGetSortFromOp(op, l); Boolean upsert = getUpsertFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + if (sorts != null) { + options = options.sort(sorts); } if ( upsert != null ){ options = options.upsert(upsert); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java index e7d6fb288..18cbcda0c 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOneOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionLegacyFindOneOpDispenser extends DataApiOpDispense private CollectionFindOneOptions getCollectionFindOneOptions(ParsedOp op, long l) { CollectionFindOneOptions options = new CollectionFindOneOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = legacyGetSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java index df23f177e..834040a38 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyFindOpDispenser.java @@ -55,9 +55,9 @@ public class DataApiCollectionLegacyFindOpDispenser extends DataApiOpDispenser { private CollectionFindOptions getCollectionFindOptions(ParsedOp op, long l) { CollectionFindOptions options = new CollectionFindOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = legacyGetSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java index 452ac5dd2..46a2fc6df 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyReplaceOneOpDispenser.java @@ -63,9 +63,9 @@ public class DataApiCollectionLegacyReplaceOneOpDispenser extends DataApiOpDispe private CollectionReplaceOneOptions getCollectionReplaceOneOptions(ParsedOp op, long l) { CollectionReplaceOneOptions options = new CollectionReplaceOneOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = legacyGetSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } Projection[] projection = getProjectionFromOp(op, l); if (projection != null) { diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java index f9f4e3b81..348f5c38b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionLegacyUpdateOneOpDispenser.java @@ -60,11 +60,10 @@ public class DataApiCollectionLegacyUpdateOneOpDispenser extends DataApiOpDispen private CollectionUpdateOneOptions getCollectionUpdateOneOptions(ParsedOp op, long l) { CollectionUpdateOneOptions options = new CollectionUpdateOneOptions(); - Sort sort = getSortFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + Sort[] sorts = legacyGetSortFromOp(op, l); + if (sorts != null) { + options = options.sort(sorts); } - Optional> upsertFunction = op.getAsOptionalFunction("upsert", Boolean.class); if (upsertFunction.isPresent()) { options = options.upsert(upsertFunction.get().apply(l)); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java index ec47efee5..0b3cb5f4b 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCollectionUpdateOneOpDispenser.java @@ -60,10 +60,10 @@ public class DataApiCollectionUpdateOneOpDispenser extends DataApiOpDispenser { private CollectionUpdateOneOptions getCollectionUpdateOneOptions(ParsedOp op, long l) { CollectionUpdateOneOptions options = new CollectionUpdateOneOptions(); - Sort sort = getSortFromOp(op, l); + Sort[] sorts = getSortFromOp(op, l); Boolean upsert = getUpsertFromOp(op, l); - if (sort != null) { - options = options.sort(sort); + if (sorts != null) { + options = options.sort(sorts); } if ( upsert != null ){ options = options.upsert(upsert); diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java index 3cc775575..171853a12 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiOpDispenser.java @@ -39,6 +39,7 @@ import io.nosqlbench.adapters.api.templating.ParsedOp; import java.util.*; import java.util.function.LongFunction; +import java.util.stream.Collectors; import java.util.stream.Stream; public abstract class DataApiOpDispenser extends BaseOpDispenser { @@ -52,8 +53,8 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser sorts = null; long sortKeyCount = Stream.of("sort", "vector", "vectorize").filter(op::isDefined).count(); if (sortKeyCount > 1) { @@ -66,19 +67,30 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser sortFields = sortFunction.get().apply(l); - String sortOrder = sortFields.get("type").toString(); - String sortField = sortFields.get("field").toString(); - switch(sortOrder) { - case "asc" -> sort = Sort.ascending(sortField); - case "desc" -> sort = Sort.descending(sortField); - } + + sorts = sortFields.entrySet().stream() + .map(e -> { + String field = e.getKey(); + String sortOrder = String.valueOf(e.getValue()).trim(); + if (sortOrder.equalsIgnoreCase("asc") || sortOrder.equalsIgnoreCase("ascending")) { + return Sort.ascending(field); + } else if (sortOrder.equalsIgnoreCase("desc") || sortOrder.equalsIgnoreCase("descending")) { + return Sort.descending(field); + } else { + throw new OpConfigError( + "Invalid sort order '" + sortOrder + "' for field '" + field + + "'; expected 'asc' or 'desc' (case-insensitive)." + ); + } + }) + .collect(Collectors.toList()); } if (op.isDefined("vector")) { float[] vector = getVectorValues(op, l); if (vector != null) { // TODO use DataAPIVector as soon as the client allows here: - sort = Sort.vector(vector); + sorts = List.of(Sort.vector(vector)); } } @@ -86,11 +98,14 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser> vzeFunction = op.getAsOptionalFunction("vectorize", String.class); if (vzeFunction.isPresent()){ String vectorize = vzeFunction.get().apply(l); - sort = Sort.vectorize(vectorize); + sorts = List.of(Sort.vectorize(vectorize)); } } - return sort; + if (sorts != null) { + return sorts.toArray(new Sort[0]); + } + return null; } protected Filter getFilterFromOp(ParsedOp op, long l) { @@ -534,6 +549,55 @@ public abstract class DataApiOpDispenser extends BaseOpDispenser sorts = null; + + long sortKeyCount = Stream.of("sort", "vector", "vectorize").filter(op::isDefined).count(); + if (sortKeyCount > 1) { + throw new OpConfigError( + "Can sort by only one of: 'sort' (regular asc/desc), 'vector', 'vectorize' in an op." + ); + } + + Optional> sortFunction = op.getAsOptionalFunction("sort", Map.class); + if (sortFunction.isPresent()) { + @SuppressWarnings("unchecked") + Map sortFields = sortFunction.get().apply(l); + String sortOrder = sortFields.get("type").toString(); + String sortField = sortFields.get("field").toString(); + switch(sortOrder) { + case "asc" -> sorts = List.of(Sort.ascending(sortField)); + case "desc" -> sorts = List.of(Sort.descending(sortField)); + } + } + + if (op.isDefined("vector")) { + float[] vector = getVectorValues(op, l); + if (vector != null) { + // TODO use DataAPIVector as soon as the client allows here: + sorts = List.of(Sort.vector(vector)); + } + } + + if (op.isDefined("vectorize")) { + Optional> vzeFunction = op.getAsOptionalFunction("vectorize", String.class); + if (vzeFunction.isPresent()){ + String vectorize = vzeFunction.get().apply(l); + sorts = List.of(Sort.vectorize(vectorize)); + } + } + + if (sorts != null) { + return sorts.toArray(new Sort[0]); + } + return null; + } + @SuppressWarnings("unchecked") protected CollectionDefinition legacyGetCollectionDefinitionFromOp(ParsedOp op, long l) { CollectionDefinition optionsBldr = new CollectionDefinition(); From 92009524eff690b7347abfe4a80813457c241485 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 24 Sep 2026 18:44:36 +0200 Subject: [PATCH 43/46] dataapi adapter documentation --- .../resources/activities/astra_kv_dapi.yaml | 254 ----------- .../activities/create_collection.yaml | 11 - .../activities/data_api_workload.yaml | 274 ++++++++++++ .../resources/activities/delete_many.yaml | 18 - .../main/resources/activities/delete_one.yaml | 13 - .../resources/activities/drop_collection.yaml | 9 - .../activities/estimated_document_count.yaml | 9 - .../activities/example_workload.yaml | 47 ++ .../activities/example_workload_legacy.yaml | 51 +++ .../src/main/resources/activities/find.yaml | 26 -- .../main/resources/activities/find_one.yaml | 26 -- .../activities/find_one_and_delete.yaml | 25 -- .../activities/find_one_and_update.yaml | 4 - .../resources/activities/insert_many.yaml | 17 - .../main/resources/activities/insert_one.yaml | 10 - .../activities/insert_one_vector.yaml | 11 - .../activities/legacy_ops_reference.yaml | 403 ++++++++++++++++++ .../activities/list_collection_names.yaml | 9 - .../activities/list_collections.yaml | 9 - .../resources/activities/ops_reference.yaml | 343 +++++++++++++++ .../src/main/resources/dataapi.md | 80 +++- 21 files changed, 1196 insertions(+), 453 deletions(-) delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/astra_kv_dapi.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/create_collection.yaml create mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/delete_many.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/delete_one.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/drop_collection.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/estimated_document_count.yaml create mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload.yaml create mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload_legacy.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/find.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/find_one.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_delete.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_update.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/insert_many.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one_vector.yaml create mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/list_collection_names.yaml delete mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/list_collections.yaml create mode 100644 nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/astra_kv_dapi.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/astra_kv_dapi.yaml deleted file mode 100644 index baeacb2b5..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/astra_kv_dapi.yaml +++ /dev/null @@ -1,254 +0,0 @@ -min_version: "5.21.0" - -description: | - A basic workload that uses the DataStax Data API Client in Java, emulating what - applications would do in the native stack. - variations: - without vector: - with _id: - search by id= - search by id< - NOT USED: with uuid: - with vector: - with _id: - search by id= - search by id< - vector search with filter by id< - vector search with vector ~ - with uuid: - vector search with vector ~ - - cardinality=TEMPLATE(cardinality,1000) - collection=TEMPLATE(collection,keyvalue) - dimensions=TEMPLATE(dimensions,1536) - similarity=TEMPLATE(similarity,COSINE) - keycount=TEMPLATE(keycount,TEMPLATE(cardinality)) - valuecount=TEMPLATE(valuecount,TEMPLATE(cardinality)) - rampup-threads=TEMPLATE(rampup-threads,100) - - -scenarios: - - astra_dapi_kv_id: - schema: >- - run driver=dataapi - tags==block:schema_kv - threads==1 cycles==UNDEF - rampup: >- - run driver=dataapi - tags==block:rampup_kv_id - cycles===TEMPLATE(rampup-cycles,TEMPLATE(cardinality)) - threads=TEMPLATE(rampup-threads) - errors=count - find_kv_by_id: >- - run driver=dataapi - tags==block:find_kv_by_id - cycles===TEMPLATE(main-cycles,1000) - threads=auto errors=count - find_kv_lt_id: >- - run driver=dataapi - tags==block:find_kv_lt_id - cycles===TEMPLATE(main-cycles,1000) - threads=auto errors=count - - astra_dapi_v1536_id: - schema_vector: >- - run driver=dataapi - tags==block:schema_v1536 - threads==1 cycles==UNDEF - rampup_vector: >- - run driver=dataapi - tags==block:rampup_v1536_id - cycles===TEMPLATE(rampup-cycles,TEMPLATE(cardinality)) - threads=TEMPLATE(rampup-threads) - errors=count - find_kv_by_id: >- - run driver=dataapi - tags==block:find_kv_by_id - cycles===TEMPLATE(main-cycles,1000) - threads=auto errors=count - find_kv_lt_id: >- - run driver=dataapi - tags==block:find_kv_lt_id - cycles===TEMPLATE(main-cycles,1000) - threads=auto errors=count - find_by_vector: >- - run driver=dataapi - tags==block:find_by_vector - cycles===TEMPLATE(main-cycles,TEMPLATE(cardinality)) - threads=auto errors=count - find_by_vector_lt_id: >- - run driver=dataapi - tags==block:find_by_vector_lt_id - cycles===TEMPLATE(main-cycles,TEMPLATE(cardinality)) - threads=auto errors=count - - astra_dapi_v1536_uuid: - schema_vector: >- - run driver=dataapi - tags==block:schema_v1536 - threads==1 cycles==UNDEF - rampup_vector: >- - run driver=dataapi - tags==block:rampup_v1536_uuid - cycles===TEMPLATE(rampup-cycles,TEMPLATE(cardinality)) - threads=TEMPLATE(rampup-threads) - errors=count - find_by_vector: >- - run driver=dataapi - tags==block:find_by_vector - cycles===TEMPLATE(main-cycles,TEMPLATE(cardinality)) - threads=auto errors=count - -bindings: - - seq_key: Mod(TEMPLATE(keycount)); ToString() -> String - seq_value: Hash(); Mod(TEMPLATE(valuecount)); ToString() -> String - rw_key: TEMPLATE(keydist,Uniform(0,TEMPLATE(keycount))); ToString() -> String - rw_key_num: TEMPLATE(keydist,Uniform(0,TEMPLATE(keycount))); - rw_value: Hash(); TEMPLATE(valdist,Uniform(0,TEMPLATE(valuecount))); ToString() -> String - vector_value: HashedFloatVectors(TEMPLATE(dimensions,1536)); - request_id: ToHashedUUID(); ToString(); - -params: - cl: TEMPLATE(cl,LOCAL_QUORUM) - instrument: true - -blocks: - - reset_schema: - ops: - drop_index: - raw: |- - DROP INDEX IF EXISTS TEMPLATE(keyspace, baselines).TEMPLATE(table,keyvalue)_value_idx; - drop-table: - raw: |- - DROP TABLE IF EXISTS TEMPLATE(keyspace, baselines).TEMPLATE(table,keyvalue); - -# Schema - - schema_kv: - ops: - delete_collection_op: - delete_collection: "TEMPLATE(collection)" - create_collection_op: - create_collection: "TEMPLATE(collection)" - - schema_v1536: - ops: - delete_collection_op_v: - delete_collection: "TEMPLATE(collection)_v" - create_collection_op_v: - create_collection: "TEMPLATE(collection)_v" - dimensions: TEMPLATE(dimensions) - similarity: TEMPLATE(similarity) - -# Rampup - - rampup_kv_id: - ops: - insert_one_op: - insert_one: "TEMPLATE(collection)" - document: - _id: "{seq_key}" - value: "{seq_value}" - -# rampup_kv_uuid: -# ops: -# insert_one_op: -# insert_one: "TEMPLATE(collection)" -# document: -# value: "{seq_value}" - - - rampup_v1536_id: - ops: - insert_one_op_v: - insert_one_vector: "TEMPLATE(collection)_v" - document: - _id: "{seq_key}" - value: "{seq_value}" - vector: "{vector_value}" - - rampup_v1536_uuid: - ops: - insert_one_op_v: - insert_one_vector: "TEMPLATE(collection)_v" - document: - value: "{seq_value}" - vector: "{vector_value}" - - find_kv_by_id: - ops: - find_op: - find: "TEMPLATE(collection)" - filters: - - conjunction: "and" - operator: "eq" - field: "_id" - value: "{rw_key}" - - find_kv_lt_id: - params: - ratio: 5 - ops: - find_kv_id_lt: - find: "TEMPLATE(collection)" - filters: - - conjunction: "and" - operator: "lt" - field: "_id" - value: "{rw_key_num}" - - find_by_vector_lt_id: - params: - ratio: 5 - ops: - find_kv_id_lt: - find: "TEMPLATE(collection)" - filters: - - conjunction: "and" - operator: "lt" - field: "_id" - value: "{rw_key_num}" - vector: "{vector_value}" - - find_by_vector: - params: - ratio: 5 - ops: - find_op_filter_v: - find_vector_filter: "TEMPLATE(collection)" - vector: "{vector_value}" - -# main_ann_with_vector_limit_20: -# params: -# ratio: 5 -# ops: -# find_op: -# find: "TEMPLATE(collection)" -# sort: -# vector: "{vector_value}" -# options: -# limit: 20 -# schema_with_text_sai: -# ops: -# delete_collection_op: -# delete_collection: "TEMPLATE(collection)" -# create_collection_op: -# create_collection: "TEMPLATE(collection)" -# rampup_with_text_sai: -# ops: -# insert_one_op: -# insert_one: "TEMPLATE(collection)" -# document: -# _id: "{seq_key}" -# value: "{seq_value}" -# main_read_with_text_sai: -# params: -# ratio: 5 -# ops: -# find_op: -# find: "TEMPLATE(collection)" -# filter: -# value: "{rw_value}" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/create_collection.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/create_collection.yaml deleted file mode 100644 index 66ebc5fdf..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/create_collection.yaml +++ /dev/null @@ -1,11 +0,0 @@ -scenarios: - default: - create_collection: run driver=dataapi tags==blocks:create_collection cycles=1 - -blocks: - create_collection: - ops: - op1: - create_collection: "collectionName" - dimensions: 10 - similarity: "COSINE" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml new file mode 100644 index 000000000..8583592de --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml @@ -0,0 +1,274 @@ +# Run with e.g.: +# +# nb TODO.yaml \ +# astraApiEndpoint=$ASTRA_DB_API_ENDPOINT \ +# astraToken=$ASTRA_DB_APPLICATION_TOKEN \ +# namespace=$ASTRA_DB_KEYSPACE \ +# [main-cycles=] \ +# [rampup-insertmany-cycles=] +# +# where = data_api_scenario_base / data_api_scenario_vector + +description: | + A simple workload that uses the Data API Client to perform + writes, reads and vector reads similar to a realistic general-purpose application. + One scenario does not involve vectors, the other does. + The vector scenario demonstrates bulk insert (which can be done regardless of vector or not). + + data_api_scenario_base: + schema + rampup (single-document insertions) + find one by document _id + find one by another document field + find (many) with a inequality filter on a field + data_api_scenario_vector: + schema + rampup (single-document insertions) + rampup (fewer multi-document insert-many) + find one by document _id + find one by another document field + find (many) with a inequality filter on a field + vector ANN find + vector ANN find plus filter conditions on other fields + + NOTE: 'rampup-threads' cannot exceed 'cardinality' + + cardinality=TEMPLATE(cardinality,1000) + collection=TEMPLATE(collection,dataapi_collection) + dimension=TEMPLATE(dimension,1536) + similarity=TEMPLATE(similarity,cosine) + valuecount=TEMPLATE(valuecount,TEMPLATE(cardinality)) + rampup-threads=TEMPLATE(rampup-threads,100) + rampup-insertmany-cycles=TEMPLATE(rampup-insertmany-cycles,5) + +scenarios: + + data_api_scenario_base: + schema: >- + run driver=dataapi + tags==block:schema_base + threads==1 cycles==UNDEF + rampup: + run driver=dataapi + tags==block:rampup_base + cycles===TEMPLATE(rampup-cycles,TEMPLATE(cardinality)) + threads=TEMPLATE(rampup-threads) + errors=count + find_by_id: + run driver=dataapi + tags==block:find_by_id + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + find_by_value: + run driver=dataapi + tags==block:find_by_value + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + find_by_ineq: + run driver=dataapi + tags==block:find_by_ineq + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + + data_api_scenario_vector: + schema: >- + run driver=dataapi + tags==block:schema_vector + threads==1 cycles==UNDEF + rampup: + run driver=dataapi + tags==block:rampup_vector + cycles===TEMPLATE(rampup-cycles,TEMPLATE(cardinality)) + threads=TEMPLATE(rampup-threads) + errors=count + rampup_insertmany: + run driver=dataapi + tags==block:rampup_vector_insertmany + cycles===TEMPLATE(rampup-insertmany-cycles,TEMPLATE(cardinality)) + threads=TEMPLATE(rampup-threads) + errors=count + find_by_id: + run driver=dataapi + tags==block:find_by_id + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + find_by_value: + run driver=dataapi + tags==block:find_by_value + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + find_by_ineq: + run driver=dataapi + tags==block:find_by_ineq + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + vector_find: + run driver=dataapi + tags==block:vector_find + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + filtered_vector_find: + run driver=dataapi + tags==block:filtered_vector_find + cycles===TEMPLATE(main-cycles,1000) + threads=auto + errors=count + +bindings: + my_seq: Mod(TEMPLATE(cardinality)) + my_value: Hash(); ToString() -> String + my_id: Mod(TEMPLATE(cardinality)); ToString() -> String + my_vector: Add(100); HashedFloatVectors(TEMPLATE(dimension,1536)); + # vectors for batches of "insert_many": + ins_vector_00: Add(200); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_01: Add(201); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_02: Add(202); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_03: Add(203); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_04: Add(204); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_05: Add(205); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_06: Add(206); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_07: Add(207); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_08: Add(208); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_09: Add(209); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_10: Add(210); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_11: Add(211); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_12: Add(212); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_13: Add(213); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_14: Add(214); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_15: Add(215); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_16: Add(216); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_17: Add(217); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_18: Add(218); HashedFloatVectors(TEMPLATE(dimension,1536)); + ins_vector_19: Add(219); HashedFloatVectors(TEMPLATE(dimension,1536)); + +blocks: + + schema_base: + ops: + create_collection_base_op: + db_create_collection: "TEMPLATE(collection)" + definition: {} + + schema_vector: + ops: + create_collection_vector_op: + db_create_collection: "TEMPLATE(collection)" + definition: + vector: + dimension: TEMPLATE(dimension,1536) + metric: TEMPLATE(similarity,cosine) + + rampup_base: + ops: + insert_one_base_op: + collection_insert_one: "TEMPLATE(collection)" + document: + _id: "{my_id}" + some_value: "{my_value}" + seq: "{my_seq}" + + rampup_vector: + ops: + insert_one_vector_op: + collection_insert_one: "TEMPLATE(collection)" + document: + _id: "{my_id}" + some_value: "{my_value}" + seq: "{my_seq}" + $vector: "{my_vector}" + + rampup_vector_insertmany: + ops: + insert_many_vector_op: + collection_insert_many: "TEMPLATE(collection)" + documents: + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_00}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_01}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_02}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_03}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_04}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_05}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_06}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_07}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_08}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_09}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_10}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_11}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_12}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_13}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_14}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_15}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_16}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_17}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_18}"} + - {"some_value":"{my_value}","seq":"{my_seq}","$vector":"{ins_vector_19}"} + + find_by_id: + ops: + find_by_id_op: + collection_find_one: "TEMPLATE(collection)" + filter: + _id: "{my_id}" + projection: + include: + - "value" + - "seq" + + find_by_value: + ops: + find_by_value_op: + collection_find_one: "TEMPLATE(collection)" + filter: + some_value: "{my_value}" + projection: + include: + - "*" + + find_by_ineq: + ops: + find_by_ineq_op: + collection_find: "TEMPLATE(collection)" + filter: + seq: + $lt: "{my_seq}" + limit: 10 + sort: + seq: desc + projection: + include: + - "seq" + + vector_find: + ops: + vector_find_op: + collection_find: "TEMPLATE(collection)" + limit: 10 + vector: "{my_vector}" + include_similarity: true + projection: + include: + - "seq" + + filtered_vector_find: + ops: + vector_find_op: + collection_find: "TEMPLATE(collection)" + limit: 10 + vector: "{my_vector}" + filter: + seq: + $lt: "{my_seq}" + some_value: + $exists: true + projection: + include: + - "seq" + exclude: + - "_id" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/delete_many.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/delete_many.yaml deleted file mode 100644 index 18f981631..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/delete_many.yaml +++ /dev/null @@ -1,18 +0,0 @@ -scenarios: - default: - delete_many: run driver=dataapi tags==blocks:delete_many cycles=1 - -blocks: - delete_many: - ops: - op1: - delete_many: "collectionName" - filters: - - conjunction: "and" - operator: "lt" - field: "field1" - value: 10 - - conjunction: "or" - operator: "eq" - field: "field2" - value: "value2" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/delete_one.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/delete_one.yaml deleted file mode 100644 index 2b9b7a799..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/delete_one.yaml +++ /dev/null @@ -1,13 +0,0 @@ -scenarios: - default: - delete_one: run driver=dataapi tags==blocks:delete_one cycles=1 - -blocks: - delete_one: - ops: - op1: - delete_one: "collectionName" - sort: - type: "asc" - field: "field1" - vector: "1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/drop_collection.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/drop_collection.yaml deleted file mode 100644 index 434bc92a7..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/drop_collection.yaml +++ /dev/null @@ -1,9 +0,0 @@ -scenarios: - default: - drop_collection: run driver=dataapi tags==blocks:drop_collection cycles=1 - -blocks: - drop_collection: - ops: - op1: - drop_collection: "collectionName" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/estimated_document_count.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/estimated_document_count.yaml deleted file mode 100644 index 21c7ea129..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/estimated_document_count.yaml +++ /dev/null @@ -1,9 +0,0 @@ -scenarios: - default: - estimated_document_count: run driver=dataapi tags==blocks:estimated_document_count cycles=1 - -blocks: - estimated_document_count: - ops: - op1: - estimated_document_count: "collectionName" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload.yaml new file mode 100644 index 000000000..583000081 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload.yaml @@ -0,0 +1,47 @@ +scenarios: + default: + find_one: run driver=dataapi tags==blocks:find_one cycles=2 + +# Run with e.g.: +# nb example_workload.yaml \ +# astraApiEndpoint=$ASTRA_DB_API_ENDPOINT \ +# astraToken=$ASTRA_DB_APPLICATION_TOKEN \ +# namespace=$ASTRA_DB_KEYSPACE + +bindings: + query_vector: Add(37); HashedFloatVectors(TEMPLATE(dimensions,1024)); + +blocks: + find_one: + ops: + example_regular_find: + collection_find: "TEMPLATE(collection)" + filter: + $and: + - field: + $lt: 10 + - block: + $eq: "A" + sort: + idx: asc + limit: 5 + projection: + include: + - "idx" + - "block" + exclude: + - "_id" + + example_vector_find: + collection_find: "TEMPLATE(collection)" + vector: "{query_vector}" + # alternatively: + # vector: "1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0..." + # vector: [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0...] + limit: 5 + projection: + include: + - "idx" + - "block" + exclude: + - "_id" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload_legacy.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload_legacy.yaml new file mode 100644 index 000000000..c0f8a3c31 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/example_workload_legacy.yaml @@ -0,0 +1,51 @@ +scenarios: + default: + find_one: run driver=dataapi tags==blocks:find_one cycles=2 + +# Run with e.g.: +# nb example_workload_legacy.yaml \ +# astraApiEndpoint=$ASTRA_DB_API_ENDPOINT \ +# astraToken=$ASTRA_DB_APPLICATION_TOKEN \ +# namespace=$ASTRA_DB_KEYSPACE + +bindings: + query_vector: Add(37); HashedFloatVectors(TEMPLATE(dimensions,1024)); + +blocks: + find_one: + ops: + legacy_example_regular_find: + find: "TEMPLATE(collection)" + filters: + - conjunction: "and" + operator: "lt" + field: "field" + value: 10 + - conjunction: "and" + operator: "eq" + field: "block" + value: "A" + sort: + type: "asc" + field: "idx" + limit: 5 + projection: + include: + - "idx" + - "block" + exclude: + - "_id" + + legacy_example_vector_find: + find: "TEMPLATE(collection)" + vector: "{query_vector}" + # alternatively: + # vector: "1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0..." + # vector: [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0...] + limit: 5 + projection: + include: + - "idx" + - "block" + exclude: + - "_id" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/find.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/find.yaml deleted file mode 100644 index 72b406dcd..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/find.yaml +++ /dev/null @@ -1,26 +0,0 @@ -scenarios: - default: - find: run driver=dataapi tags==blocks:find cycles=10 - -blocks: - find: - ops: - op1: - find: "collectionName" - filters: - - conjunction: "and" - operator: "lt" - field: "field1" - value: 10 - - conjunction: "or" - operator: "eq" - field: "field2" - value: "value2" - sort: - type: "asc" - field: "field1" - vector: "1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0" - projection: - include: - - "field1" - - "field2" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one.yaml deleted file mode 100644 index e86bb16a3..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one.yaml +++ /dev/null @@ -1,26 +0,0 @@ -scenarios: - default: - find_one: run driver=dataapi tags==blocks:find_one cycles=10 - -blocks: - find_one: - ops: - op1: - find_one: "collectionName" - filters: - - conjunction: "and" - operator: "lt" - field: "field1" - value: 10 - - conjunction: "or" - operator: "eq" - field: "field2" - value: "value2" - sort: - type: "asc" - field: "field1" - vector: "1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0" - projection: - include: - - "field1" - - "field2" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_delete.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_delete.yaml deleted file mode 100644 index e28b27c3c..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_delete.yaml +++ /dev/null @@ -1,25 +0,0 @@ -scenarios: - default: - find_one_and_delete: run driver=dataapi tags==blocks:find_one_and_delete cycles=1 - -blocks: - find_one_and_delete: - ops: - op1: - find_one_and_delete: "collectionName" - filters: - - conjunction: "and" - operator: "lt" - field: "field1" - value: 10 - - conjunction: "or" - operator: "eq" - field: "field2" - value: "value2" - sort: - type: "asc" - field: "field1" - projection: - include: - - "field1" - - "field2" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_update.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_update.yaml deleted file mode 100644 index edff96902..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/find_one_and_update.yaml +++ /dev/null @@ -1,4 +0,0 @@ -min_version: "5.21.0" - -description: | - TBD, similar to find_one_and_delete.yaml diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_many.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_many.yaml deleted file mode 100644 index 81a818d6f..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_many.yaml +++ /dev/null @@ -1,17 +0,0 @@ -scenarios: - default: - insert_many: run driver=dataapi tags==blocks:insert_many cycles=1 - -blocks: - insert_many: - ops: - op1: - insert_many: "collectionName" - options: - chunkSize: "1000" - concurrency: "10" - ordered: "false" - documents: - - "{valid json here}" - - "{valid json here}" - - "{valid json here}" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one.yaml deleted file mode 100644 index 567f06cd0..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one.yaml +++ /dev/null @@ -1,10 +0,0 @@ -scenarios: - default: - insert_one: run driver=dataapi tags==blocks:insert_one cycles=1 - -blocks: - insert_one: - ops: - op1: - insert_one: "collectionName" - document: "{valid json here}" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one_vector.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one_vector.yaml deleted file mode 100644 index a9bce8200..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/insert_one_vector.yaml +++ /dev/null @@ -1,11 +0,0 @@ -scenarios: - default: - insert_one: run driver=dataapi tags==blocks:insert_one cycles=1 - -blocks: - insert_one: - ops: - op1: - insert_one: "collectionName" - document: "{valid json here}" - vector: "1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0" diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml new file mode 100644 index 000000000..cd166a448 --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml @@ -0,0 +1,403 @@ +# NOTE: this file only lists the (legacy) operations and their syntax in a self-documenting comment-rich form. +# It is not a full NB workload file. Refer to the full examples for the overall format. + +blocks: + bl_do_debug: + ops: + + # LEGACY "deleteCollection", fully documented: + delcoll_legacy: + delete_collection: "TEMPLATE(collection)" + + # LEGACY "createCollection", fully documented: + crcoll_legacy: + create_collection: "TEMPLATE(collection)" + ### optional vector dimensionality (if present, it's a vector collection. Note plural, 'dimensions'): + # dimensions: 1024 + #### optional similarity function for vector (case-insensitive "COSINE"/"EUCLIDEAN"/"DOT_PRODUCT"): + # similarity: DOT_PRODUCT + #### optional (required for vectorize) service provider: + # serviceProvider: voyageAI + #### optional (required for vectorize) service model (note a typo, 'mode'): + # serviceMode: voyage-2 + #### optional KMS secret name for vectorize API key: + # serviceSharedSecretKey: SHARED_SECRET_EMBEDDING_API_KEY_VOYAGEAI + #### optional parameters map for vectorize service/model: + # serviceParameters: + # autoTruncate: true + #### optional default ID type (case-sensitive "objectId"/"uuidv6"/"uuidv7"/"uuid"): + # collectionType: objectId + #### optional, allow-list for indexing (error if denyIndex present as well): + # allowIndex: + # - aField1 + # - aField2 + #### optional, deny-list for indexing (error if allowIndex present as well): + # denyIndex: + # - aField1 + # - aField2 + + # LEGACY "insertMany", fully documented: + im_legacy: + insert_many: "TEMPLATE(collection)" + # required documents to insert (a list of strings, each a serialized JSON): + documents: + - "{\"a\": 1}" + - "{\"a\": 2}" + - "{\"a\": 3}" + #### optional, options (each must be a string if provided): + # options: + # # how to split the input list into separate requests (default 50): + # chunkSize: "20" + # # concurrency level for running chunk insertions (must be 1 if ordered=true): + # concurrency: "5" + # # ordered insertion? true = insert sequentially and fail fast; false = no order guarantees, proceed even if errors: + # ordered: "false" + # # timeout for each individual chunk insertion (milliseconds): + # timeout: "5000" + + # LEGACY "insertOne", fully documented (note: identical to new-style op except in the op name): + i1_legacy: + insert_one: "TEMPLATE(collection)" + #### required document to insert, free-form (_id can be omitted; note alternate forms for optional $vector): + document: + new: true + # $vector: [1,2,3,4,5,6,7,8,9,0] + # $vector: + # $binary: "P4AAAD+AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAA==" + + # LEGACY "insertOne" with explicit vector, fully documented: + i1vec_legacy: + insert_one_vector: "TEMPLATE(collection)" + #### required document to insert, free-form (_id can be omitted, $vector is ignored): + document: + new: true + # required vector value to come with the document (three alternate forms): + vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + # vector: "1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0" + # vector: + # - 1.0 + # - 1.0 + # - 1.0 + # - 1.0 + # - 1.0 + # - 1.0 + # - 1.0 + # - 1.0 + # - 1.0 + # - 1.0 + + # LEGACY "updateMany", fully documented: + um_legacy: + update_many: "TEMPLATE(collection)" + #### required update, free-form: + updates: + $set: + updated: "yes!" + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "old" + # value: true + #### optional upsert: + # upsert: true + + # LEGACY replace_one, fully documented: + repl1_legacy: + replace_one: "TEMPLATE(collection)" + #### required replacement document in its entirety, free-form (_id can be omitted): + document: + new: true + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "old" + # value: true + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (either include or exclude, list of fields): + # projection: + # exclude: + # - "_id" + #### optional upsert: + # upsert: true + #### optional 'returnDocument' (values: 'after'/'before') + # returnDocument: after + + # LEGACY "findOneAndReplace". Fully documented: + f1repl_legacy: + find_one_and_replace: "TEMPLATE(collection)" + #### required replacement document in its entirety, free-form (_id can be omitted): + document: + new: true + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "idx" + # value: 20 + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (either include or exclude, list of fields): + # projection: + # exclude: + # - "idx" + #### optional upsert: + # upsert: true + #### optional 'returnDocument' (values: 'after'/'before') + # returnDocument: after + + # LEGACY "findOneAndDelete". Fully documented: + f1del_legacy: + find_one_and_delete: "TEMPLATE(collection)" + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "idx" + # value: 20 + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (either include or exclude, list of fields): + # projection: + # exclude: + # - "idx" + + # LEGACY "updateOne". Fully documented: + u1_legacy: + update_one: "TEMPLATE(collection)" + #### required update (free-form): + # update: + # $set: + # updated: true + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "idx" + # value: 29 + #### optional upsert: + # upsert: true + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + + # LEGACY countDocuments. Fully documented: + cd_legacy: + count_documents: "TEMPLATE(collection)" + #### required upper bound (a client-side notion. Error thrown if result exceeds it): + upperbound: 100 + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "lt" + # field: "idx" + # value: 100 + + # LEGACY estimatedDocumentCount (only the op name differs from 'new'). Fully documented: + edc_legacy: + estimated_document_count: "TEMPLATE(collection)" + + # LEGACY delete-all, i.e. "deleteMany" with no filters (truncate). Fully documented: + da_legacy: + delete_all: "TEMPLATE(collection_to_truncate)" + + # LEGACY "deleteMany". Fully documented: + dm_legacy: + delete_many: "TEMPLATE(collection)" + #### required filter (either all 'and' or all 'or', cannot be empty): + filters: + - conjunction: "and" + operator: "gt" + field: "idx" + value: 52 + + # LEGACY "deleteOne". Fully documented: + d1_legacy: + delete_one: "TEMPLATE(collection)" + #### required filter (either all 'and' or all 'or', cannot be empty): + filters: + - conjunction: "and" + operator: "lt" + field: "idx" + value: 100 + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + + # LEGACY "find (no vectors)". Fully documented: + find_legacy: + find: "TEMPLATE(collection)" + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "lt" + # field: "idx" + # value: 80 + #### optional limit: + # limit: 40 + #### optional skip: + # skip: 1 + #### optional includeSimilarity (default to true in this op): + # includeSimilarity: true + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (either include or exclude, list of fields): + # projection: + # include: + # - "idx" + #### optional pageState to start the find from: + # pageState: "LQAAAAEBAAAAJDc1NDgyNzk5LTQwN2ItNGEyOC04ODI3LTk5NDA3YmFhMjg4YQDwf///zQA=" + + # LEGACY "find with vector". Fully documented: + find_vector_legacy: + find_vector: "TEMPLATE(collection)" + #### required sort vector (float list/string repr with commas): + vector: "{seq_vector}" + #### optional, limit (defaults to 100): + # limit: 3 + + # LEGACY "find with vector and a filter". Fully documented: + find_vector_filter_legacy: + find_vector_filter: "TEMPLATE(collection)" + #### required sort vector (float list/string repr with commas): + vector: "{seq_vector}" + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "lt" + # field: "idx" + # value: 80 + #### optional, limit (defaults to 100): + # limit: 3 + + # LEGACY "findOne (by ID)". Fully documented: + find_by_id_legacy: + find_by_id: "TEMPLATE(collection)" + #### required id of the target document: + id: "zzz" + + # LEGACY "findOne". Fully documented: + f1_legacy: + find_one: "TEMPLATE(collection)" + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "field1" + # value: 74 + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (either include or exclude, list of fields): + # projection: + # include: + # - "field1" + # - "field2" + #### optional includeSimilarity (default to true in this op): + # include_similarity: false + + # LEGACY "findOneAndUpdate". Fully documented: + f1upd_legacy: + find_one_and_update: "TEMPLATE(collection)" + #### required update (can only 1 update op, legacy op limitation): + updates: + update: + operation: inc + field: "incd field" + value: 500 + #### optional sort (can only 1 sort, not if 'vector/ize'): + # sort: + # type: "asc" + # field: "idx" + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "field1" + # value: 74 + #### optional upsert: + # upsert: true + + # LEGACY find-distinct (client-side operation). Fully documented: + find_distinct_op_legacy: + find_distinct: "TEMPLATE(collection)" + #### required field to read: + fieldName: "the_field" + #### optional filter (either all 'and' or all 'or'): + # filters: + # - conjunction: "and" + # operator: "eq" + # field: "field1" + # value: 74 + #### optional class for the result (default: java.lang.String) + # resultClass: "java.lang.Double" + + # LEGACY create collection 'with class' (the 'with class' is a client-side operation only). Fully documented: + create_collection_with_class_legacy: + create_collection_with_class: "TEMPLATE(collection_to_create)" + #### required class name for the collection instance returned (default is shown): + createClass: "com.datastax.astra.client.collections.definition.documents.Document" + #### optional vector dimension: + # dimensions: 1024 + #### optional similarity function (for vector): + # similarity: "DOT_PRODUCT" + #### optional default ID type: + # collectionType: objectId + #### optional vectorize provider: + # serviceProvider: voyageAI + #### optional vectorize model (note the param typo, 'Mode'): + # serviceMode: "voyage-2" + #### optional embedding API key name in KMS: + # serviceSharedSecretKey: SHARED_SECRET_EMBEDDING_API_KEY_VOYAGEAI + #### optional parameters for the embedding service (depend on model): + # serviceParameters: + # autoTruncate: true + #### optional selective indexing (only one of 'allowIndex'/'denyIndex'): + # allowIndex: + # - field1 + # - field2 diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/list_collection_names.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/list_collection_names.yaml deleted file mode 100644 index 4234ccc58..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/list_collection_names.yaml +++ /dev/null @@ -1,9 +0,0 @@ -scenarios: - default: - list_collection_names: run driver=dataapi tags==blocks:list_collection_names cycles=1 - -blocks: - list_collection_names: - ops: - op1: - list_collection_names: TBD diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/list_collections.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/list_collections.yaml deleted file mode 100644 index 87d2b9ac8..000000000 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/list_collections.yaml +++ /dev/null @@ -1,9 +0,0 @@ -scenarios: - default: - list_collections: run driver=dataapi tags==blocks:list_collections cycles=1 - -blocks: - list_collections: - ops: - op1: - list_collections: TBD diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml new file mode 100644 index 000000000..24aed271a --- /dev/null +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml @@ -0,0 +1,343 @@ +# NOTE: this file only lists the operations and their syntax in a self-documenting comment-rich form. +# It is not a full NB workload file. Refer to the full examples for the overall format. + +blocks: + bl_do_debug: + ops: + + # NEW "deleteCollection", fully documented: + delcoll: + db_delete_collection: "TEMPLATE(collection)" + + # NEW "createCollection", fully documented: + crcoll: + db_create_collection: "TEMPLATE(collection)" + #### required collection definition (free-form, must be valid Data API syntax) + definition: + vector: + dimension: 1024 + metric: "dot_product" + service: + provider: "voyageAI" + modelName: "voyage-2" + authentication: + providerKey: "SHARED_SECRET_EMBEDDING_API_KEY_VOYAGEAI" + parameters: + autoTruncate: true + indexing: + allow: + - aField1 + - aField2 + defaultId: + type: objectId + + # NEW "insertMany", fully documented: + im: + collection_insert_many: "TEMPLATE(collection)" + # required documents to insert, list of free-form objects: + documents: + - {"a": 1} + - a: 2 + b: my_string + c: + c1: subitem1 + c2: 1999 + - a: 3 + $vector: [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] + #### optional ordered flag, default=false (true = insert sequentially and fail fast; false = no order guarantees, proceed even if errors): + # ordered: false + #### optional for splitting the input list into separate requests (default 50): + #### NOTE: in a typical NoSQLBench workload, this should not count and not be used, meaning the amount of documents + #### submitted should be <= chunk size. This is because NB supposedly works in unit of requests to the server, + #### not mediated by manipulations from the Data API client. + # chunk_size: 20 + + # NEW "insertOne", fully documented: + i1: + collection_insert_one: "TEMPLATE(collection)" + #### required document to insert, free-form (_id can be omitted; note alternate forms for optional $vector): + document: + newv2: true + # $vector: [1,2,3,4,5,6,7,8,9,0] + # $vector: + # $binary: "P4AAAD+AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAA==" + + # NEW "updateMany", fully documented: + um: + collection_update_many: "TEMPLATE(collection)" + #### (Note: may fail to update more than first page until fix to https://github.com/datastax/astra-db-java/issues/106 is released) + #### required update (free-form): + # update: + # $set: + # updated: "yes!" + #### optional filter (free-form): + # filter: + # $and: + # - marker_field: present + # - not_a_field: + # $exists: false + #### optional upsert: + # upsert: true + + # NEW "findOneAndReplace". Fully documented: + f1repl: + collection_find_one_and_replace: "TEMPLATE(collection)" + #### required replacement document in its entirety, free-form (_id can be omitted): + replacement: + new: true + #### optional filter (free-form): + # filter: + # $and: + # - _id: + # $ne: abcd0123 + # - not_a_field: + # $exists: false + #### optional upsert: + # upsert: true + #### optional 'return_document' (values: 'after'/'before') + # return_document: after + #### optional sort (order matters; can't use if 'vector/ize'): + # sort: + # block: asc + # idx: desc + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (lists of fields; include and exclude can coexist only for special fields): + # projection: + # exclude: + # - "idx" + + # NEW "findOneAndDelete". Fully documented: + f1del: + collection_find_one_and_delete: "TEMPLATE(collection)" + #### optional filter (free-form): + # filter: + # $and: + # - idx: + # $gte: 21 + # - not_a_field: + # $exists: false + #### optional sort (order matters; can't use if 'vector/ize'): + # sort: + # block: asc + # idx: desc + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (lists of fields; include and exclude can coexist only for special fields): + # projection: + # exclude: + # - "idx" + + # NEW "updateOne". Fully documented: + u1: + collection_update_one: "TEMPLATE(collection)" + #### required update (free-form): + update: + $set: + updated: true + #### optional filter (free-form): + # filter: + # $and: + # - idx: 29 + # - not_a_field: + # $exists: false + #### optional upsert: + # upsert: true + #### optional sort (order matters; can't use if 'vector/ize'): + # sort: + # block: asc + # idx: desc + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + + # NEW "countDocuments". Fully documented: + cd: + collection_count_documents: "TEMPLATE(collection)" + #### optional filter (free-form): + # filter: + # fake_field: + # $exists: false + #### optional upper bound (a client-side notion. *If provided*, error thrown when exceeded) + # upper_bound: 100 + + # NEW "estimatedDocumentCount". Fully documented: + edc: + collection_estimated_document_count: "TEMPLATE(collection)" + + # NEW "deleteMany". Fully documented: + dm: + collection_delete_many: "TEMPLATE(collection)" + #### required filter (free-form. truncate with 'filter: {}') + filter: + idx: + $gt: 40 + + # NEW "deleteOne". Fully documented: + d1: + collection_delete_one: "TEMPLATE(collection)" + #### required filter (free-form): + filter: + $and: + - idx: + $gte: 45 + - the_field: + $exists: false + #### optional sort (order matters; can't use if 'vector/ize'): + # sort: + # block: asc + # idx: desc + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + + # NEW "find". Fully documented: + f: + collection_find: "TEMPLATE(collection)" + #### optional filter (free-form): + # filter: + # $or: + # - idx: + # $lt: 99 + # - idx: + # $exists: false + #### optional sort (order matters; can't use if 'vector/ize'): + # sort: + # block: asc + # idx: desc + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional limit: + # limit: 36 + #### optional skip (only with non-vector sorting): + # skip: 45 + #### optional projection (lists of fields; include and exclude can coexist only for special fields): + # projection: + # include: + # - "idx" + # - "bloppo" + #### optional includeSimilarity (default true for nb): + # include_similarity: false + #### optional includeSortVector (default false): + # include_sort_vector: true + + # NEW "findOne". Fully documented: + f1: + collection_find_one: "TEMPLATE(collection)" + #### optional filter (free-form): + # filter: + # $and: + # - field1: "{the_value}" + # - field2: + # $eq: "{the_value}" + #### optional sort (order matters; can't use if 'vector/ize'): + # sort: + # block: asc + # idx: desc + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional projection (lists of fields; include and exclude can coexist only for special fields): + # projection: + # include: + # - "field1" + # - "field2" + #### optional includeSimilarity: + # include_similarity: false + + # NEW "findOneAndUpdate". Fully documented: + f1upd: + collection_find_one_and_update: "TEMPLATE(collection)" + #### required update + update: + $set: + myfield2: "new_val" + $inc: + myfield: 200 + myfield1: 20 + #### optional sort (order matters; can't use if 'vector/ize'): + # sort: + # block: asc + # idx: desc + #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): + # vector: "{seq_vector_w}" + #### optional vectorize (not if 'sort/vector'): + # vectorize: "query string" + #### optional filter (free-form): + # filter: + # $and: + # - field1: "{the_value}" + # - field2: + # $eq: "{the_value}" + #### optional upsert: + # upsert: true + + # NEW "findAndRerank", fully documented: + farr: + collection_find_and_rerank: "TEMPLATE(collection)" + #### required sort clause. Must have '$hybrid' key, with one of the various forms accepted (also depending on collection settings): + sort: + $hybrid: bla + ## alternative (explicit per-leg) sort form: + # sort: + # $hybrid: + # $vectorize: bli + # $lexical: blo + ## alternative (explicit per-leg) sort form: + # sort: + # $hybrid: + # $vector: [0.1,0.2,0.3] + # $lexical: "bla" + ## alternative (no-lexical) sort form: + # sort: + # $hybrid: + # $vectorize: bli + ## alternative (no-lexical) sort form: + # sort: + # $hybrid: + # $vector: [0.1,0.2,0.3] + #### optional filter (free-form): + # filter: + # $vectorize: + # $exists: true + #### optional projection (lists of fields; include and exclude can coexist only for special fields): + # projection: + # include: + # - $vectorize + # exclude: + # - _id + #### optional limit: + # limit: 1 + #### optional hybridLimits (can have either form): + # hybrid_limits: 10 + ## alternative (explicit per-leg) hybridLimits form: + # hybrid_limits: + # $vector: 11 + # $lexical: 9 + #### optional rerankOn: + # rerank_on: "$lexical" + #### optional rerankQuery: + # rerank_query: "ble" + #### optional includeScores (default false): + # include_scores: true + #### optional includeSortVector (default false): + # include_sort_vector: true + #### optional rerank override for this one call: + #### (Note: may not work until fix to https://github.com/datastax/astra-db-java/issues/109 released) + # rerank: + # provider: theProvider" + # modelName: "theModelName" + # authentication: + # providerKey: "bla" + # parameters: + # param1: value1 + # param2: 999 diff --git a/nb-adapters/adapter-dataapi/src/main/resources/dataapi.md b/nb-adapters/adapter-dataapi/src/main/resources/dataapi.md index 7c7f9f02e..e9d117051 100644 --- a/nb-adapters/adapter-dataapi/src/main/resources/dataapi.md +++ b/nb-adapters/adapter-dataapi/src/main/resources/dataapi.md @@ -1,6 +1,82 @@ --- source: nb-adapters/adapter-dataapi/src/main/resources/dataapi.md --- -# Data API -## DataStax Data API Adapter +# Data API adapter + +This is a NB adapter for the [Data API](https://github.com/stargate/data-api), an HTTP API that can run on top of Cassandra and DataStax Astra DB. + +The adapter is built on top of the [Java client](https://github.com/datastax/astra-db-java) for the Data API and exposes the same primitives as the Data API, in a 1:1 relation between ops and Data API commands wherever possible and exposing all of the command options when it makes sense to do so. + +## Command-line parameters + +_Note: this release of the adapter is designed to connect to **DataStax Astra DB's Data API** specifically. All examples refer to this case. Subsequent releases will expand the scope to non-Astra-DB instances of Data API._ + +Connection to the Data API requires an **API Endpoint** and an **Application Token**, plus specification of a **keyspace** to operate in. These are required parameters when launching a NB workload targeting the Data API: + +``` +astraToken="..." +astraApiEndpoint="https://..." +namespace="the_keyspace" +``` + +These values are used by the adapter to establish a `DataAPIClient`, from which all subsequent operations are spawned. + +## Legacy vs. "new-style" operation + +In September 2026, a major rework of the ops has been initiated, essentially marking all operations existing so far as "legacy" and introducing a whole new set of ops, coming with more extensible naming conventions (e.g. the legacy `find` op has become `collection_find`). The overhaul has reached its first milestone (collection CRUD and all collection operations). + +The legacy operations received bug fixes (plus obvious additive extensions to their behaviour when it made sense to). So, no pre-existing workload will break. However, the user is encouraged to build new workload exclusively using the new-style operations. + +For a detailed catalog of the legacy and the new-style operations, with their syntax, consult the "Examples" section below. + +### Current status of the overhaul + +**Done:** + +- all collection DML ops; +- create/delete collection DDL; +- All known bugs in legacy operations are fixed. + +**Coming next:** + +- introduction of Table support; +- Administrative functions (create keyspace and so on), currently left as they were before the overhaul; +- Ability to target non-Astra and non-prod environments in full; +- Ability to supply special Data API-related secrets (such as embedding provider API keys for $vectorize operations). + +## Usage notes (new-style ops) + +Most commands support a free-form syntax for some of their parameters, such as the collection definition for `db_create_collection` or the insertee document in `collection_insert_one`. This is to give the most flexibility and future-proofing the op in case new syntax is added by the Data API. + +In other cases, when it was deemed more convenient, the syntax is more constrained. All specifications are given in the supporting example op YAMLs under `activities/`. + +### Vectors + +Many commands allow to supply **vectors**: these can be expressed in the YAML: + +- literally, as lists of (floating-point) numbers: `[0.1,-3.2,1.9]`; +- literally, as a string containing comma-separated floating points: `"0.1,-3.2,1.9"`; +- via an appropriate binding, e.g. `"{the_vector_binding}"`. + +In any case, whenever the API Client is equipped to do so, vectors are transmitted in the bandwidth-optimized binary-encoded form regardless of how they are given. One _should not_ manually construct the binary-encoding syntax (e.g. as part of an insertee document for a `collection_insert_one` op). + +## Client vs. 'raw Data API payloads' + +An important virtue of the Java Data API client is that it handles headers, authentication, encoding/decoding of payloads and responses - with minimal overhead. + +On the other hand, the client builds higher-level convenience features on top of the raw HTTP requests underlying the API: so, for example, what for the client is a single 200-item `insertMany(...)` invocation translates to a certain number of "chunked" Data API requests, each one inserting some of the items and executed with a degree of (client-managed) concurrency that depends on various settings. _This is a kind of sophistication that a typical usage of NB would not want_. + +For this reason, the adapter strives to avoid patterns that would trigger such "too complex" behaviours: for instance, the client concurrency for multiple insertions is always hardcoded to one, leaving management of concurrent requests purely on the NB side. + +It is, however, an ultimate responsibility of the Data API-savvy NB user to ensure full compliance with this tenet, for example never packing more than a pageful of items into a `collection_insert_many` operation's `documents` property. + +## Examples + +Consult the self-documenting YAML examples here: + +- a simple [minimal running workload](activities/example_workload.yaml); + - (a simple [legacy minimal running workload](activities/example_workload_legacy.yaml)); +- a realistic, [ready-to-run workload](activities/data_api_workload.yaml) demonstrating several ops +- [new-style ops full reference](activities/ops_reference.yaml); + - ([legacy ops full reference](activities/legacy_ops_reference.yaml)). From 3cb8ae06940741dce9959d72148ccc2cc294f37d Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Thu, 24 Sep 2026 23:55:07 +0200 Subject: [PATCH 44/46] remove extensive data api logging for PR --- .../java/io/nosqlbench/adapter/dataapi/DataApiSpace.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java index b38d419e9..657385f92 100644 --- a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java +++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java @@ -78,11 +78,7 @@ public class DataApiSpace extends BaseSpace { } private void createClient() { - // TODO: remove this - it's to log Data API requests and responses - DataAPIClientOptions options = new DataAPIClientOptions() - .logRequests(); - - this.dataAPIClient = new DataAPIClient(astraToken, /* S */ options); + this.dataAPIClient = new DataAPIClient(astraToken); if (namespace != null) { this.database = dataAPIClient.getDatabase(astraApiEndpoint, namespace); } else { From 401489148aa0ec6e51567bc19902690e9f24e338 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Fri, 25 Sep 2026 16:57:24 +0200 Subject: [PATCH 45/46] correct workload name in workload instructions --- .../src/main/resources/activities/data_api_workload.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml index 8583592de..52ab0aac5 100644 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/data_api_workload.yaml @@ -1,11 +1,11 @@ # Run with e.g.: # -# nb TODO.yaml \ +# nb data_api_workload.yaml \ # astraApiEndpoint=$ASTRA_DB_API_ENDPOINT \ # astraToken=$ASTRA_DB_APPLICATION_TOKEN \ # namespace=$ASTRA_DB_KEYSPACE \ # [main-cycles=] \ -# [rampup-insertmany-cycles=] +# [rampup-insertmany-cycles=] # # where = data_api_scenario_base / data_api_scenario_vector From 339aa7b94d6db3a24aac5bc383ef454a72443c11 Mon Sep 17 00:00:00 2001 From: Stefano Lottini <236640031+sl-at-ibm@users.noreply.github.com> Date: Fri, 25 Sep 2026 18:07:23 +0200 Subject: [PATCH 46/46] last touches to the self-documenting all-ops yamls --- .../activities/legacy_ops_reference.yaml | 58 ++++++++++--------- .../resources/activities/ops_reference.yaml | 36 ++++++------ 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml index cd166a448..187df015d 100644 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/legacy_ops_reference.yaml @@ -2,7 +2,7 @@ # It is not a full NB workload file. Refer to the full examples for the overall format. blocks: - bl_do_debug: + my_block: ops: # LEGACY "deleteCollection", fully documented: @@ -119,7 +119,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (either include or exclude, list of fields): @@ -148,7 +148,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (either include or exclude, list of fields): @@ -174,7 +174,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (either include or exclude, list of fields): @@ -186,9 +186,9 @@ blocks: u1_legacy: update_one: "TEMPLATE(collection)" #### required update (free-form): - # update: - # $set: - # updated: true + update: + $set: + updated: true #### optional filter (either all 'and' or all 'or'): # filters: # - conjunction: "and" @@ -202,7 +202,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" @@ -250,7 +250,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" @@ -274,7 +274,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (either include or exclude, list of fields): @@ -288,7 +288,7 @@ blocks: find_vector_legacy: find_vector: "TEMPLATE(collection)" #### required sort vector (float list/string repr with commas): - vector: "{seq_vector}" + vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional, limit (defaults to 100): # limit: 3 @@ -296,7 +296,7 @@ blocks: find_vector_filter_legacy: find_vector_filter: "TEMPLATE(collection)" #### required sort vector (float list/string repr with commas): - vector: "{seq_vector}" + vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional filter (either all 'and' or all 'or'): # filters: # - conjunction: "and" @@ -326,7 +326,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (either include or exclude, list of fields): @@ -351,7 +351,7 @@ blocks: # type: "asc" # field: "idx" #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional filter (either all 'and' or all 'or'): @@ -382,22 +382,26 @@ blocks: create_collection_with_class: "TEMPLATE(collection_to_create)" #### required class name for the collection instance returned (default is shown): createClass: "com.datastax.astra.client.collections.definition.documents.Document" - #### optional vector dimension: + ### optional vector dimensionality (if present, it's a vector collection. Note plural, 'dimensions'): # dimensions: 1024 - #### optional similarity function (for vector): - # similarity: "DOT_PRODUCT" - #### optional default ID type: - # collectionType: objectId - #### optional vectorize provider: + #### optional similarity function for vector (case-insensitive "COSINE"/"EUCLIDEAN"/"DOT_PRODUCT"): + # similarity: DOT_PRODUCT + #### optional (required for vectorize) service provider: # serviceProvider: voyageAI - #### optional vectorize model (note the param typo, 'Mode'): - # serviceMode: "voyage-2" - #### optional embedding API key name in KMS: + #### optional (required for vectorize) service model (note a typo, 'mode'): + # serviceMode: voyage-2 + #### optional KMS secret name for vectorize API key: # serviceSharedSecretKey: SHARED_SECRET_EMBEDDING_API_KEY_VOYAGEAI - #### optional parameters for the embedding service (depend on model): + #### optional parameters map for vectorize service/model: # serviceParameters: # autoTruncate: true - #### optional selective indexing (only one of 'allowIndex'/'denyIndex'): + #### optional default ID type (case-sensitive "objectId"/"uuidv6"/"uuidv7"/"uuid"): + # collectionType: objectId + #### optional, allow-list for indexing (error if denyIndex present as well): # allowIndex: - # - field1 - # - field2 + # - aField1 + # - aField2 + #### optional, deny-list for indexing (error if allowIndex present as well): + # denyIndex: + # - aField1 + # - aField2 diff --git a/nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml b/nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml index 24aed271a..06984295e 100644 --- a/nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml +++ b/nb-adapters/adapter-dataapi/src/main/resources/activities/ops_reference.yaml @@ -2,7 +2,7 @@ # It is not a full NB workload file. Refer to the full examples for the overall format. blocks: - bl_do_debug: + my_block: ops: # NEW "deleteCollection", fully documented: @@ -59,17 +59,15 @@ blocks: document: newv2: true # $vector: [1,2,3,4,5,6,7,8,9,0] - # $vector: - # $binary: "P4AAAD+AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAD+AAAA/gAAAP4AAAA==" # NEW "updateMany", fully documented: um: collection_update_many: "TEMPLATE(collection)" #### (Note: may fail to update more than first page until fix to https://github.com/datastax/astra-db-java/issues/106 is released) #### required update (free-form): - # update: - # $set: - # updated: "yes!" + update: + $set: + updated: "yes!" #### optional filter (free-form): # filter: # $and: @@ -101,7 +99,7 @@ blocks: # block: asc # idx: desc #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector}" + # vector: [1,2,3,4,5,6,7,8,9,0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (lists of fields; include and exclude can coexist only for special fields): @@ -124,7 +122,7 @@ blocks: # block: asc # idx: desc #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector}" + # vector: [1,2,3,4,5,6,7,8,9,0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (lists of fields; include and exclude can coexist only for special fields): @@ -152,7 +150,7 @@ blocks: # block: asc # idx: desc #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector}" + # vector: [1,2,3,4,5,6,7,8,9,0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" @@ -193,7 +191,7 @@ blocks: # block: asc # idx: desc #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector}" + # vector: [1,2,3,4,5,6,7,8,9,0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" @@ -212,7 +210,7 @@ blocks: # block: asc # idx: desc #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1,2,3,4,5,6,7,8,9,0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional limit: @@ -235,15 +233,15 @@ blocks: #### optional filter (free-form): # filter: # $and: - # - field1: "{the_value}" + # - field1: "value1" # - field2: - # $eq: "{the_value}" + # $eq: 123 #### optional sort (order matters; can't use if 'vector/ize'): # sort: # block: asc # idx: desc #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1,2,3,4,5,6,7,8,9,0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional projection (lists of fields; include and exclude can coexist only for special fields): @@ -257,7 +255,7 @@ blocks: # NEW "findOneAndUpdate". Fully documented: f1upd: collection_find_one_and_update: "TEMPLATE(collection)" - #### required update + #### required update (free-form): update: $set: myfield2: "new_val" @@ -269,15 +267,15 @@ blocks: # block: asc # idx: desc #### optional vector (not if 'sort/vectorize'; float list/string repr with commas): - # vector: "{seq_vector_w}" + # vector: [1,2,3,4,5,6,7,8,9,0] #### optional vectorize (not if 'sort/vector'): # vectorize: "query string" #### optional filter (free-form): # filter: # $and: - # - field1: "{the_value}" + # - field1: "value1" # - field2: - # $eq: "{the_value}" + # $eq: 123 #### optional upsert: # upsert: true @@ -332,7 +330,7 @@ blocks: #### optional includeSortVector (default false): # include_sort_vector: true #### optional rerank override for this one call: - #### (Note: may not work until fix to https://github.com/datastax/astra-db-java/issues/109 released) + #### (Note: may not have effects until fix to https://github.com/datastax/astra-db-java/issues/109 released) # rerank: # provider: theProvider" # modelName: "theModelName"