diff --git a/.run/SCENARIO astra DAPI dapi_novector.run.xml b/.run/SCENARIO astra DAPI dapi_novector.run.xml
new file mode 100644
index 000000000..4c2231ff5
--- /dev/null
+++ b/.run/SCENARIO astra DAPI dapi_novector.run.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/astra DAPI rampup threads=1.run.xml b/.run/astra DAPI rampup threads=1.run.xml
new file mode 100644
index 000000000..e13f0c550
--- /dev/null
+++ b/.run/astra DAPI rampup threads=1.run.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/astra DAPI read.run.xml b/.run/astra DAPI read.run.xml
new file mode 100644
index 000000000..ae12e2961
--- /dev/null
+++ b/.run/astra DAPI read.run.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nb-adapters/adapter-dataapi/README.md b/nb-adapters/adapter-dataapi/README.md
new file mode 100644
index 000000000..e69de29bb
diff --git a/nb-adapters/adapter-dataapi/pom.xml b/nb-adapters/adapter-dataapi/pom.xml
new file mode 100644
index 000000000..8cd1a0691
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/pom.xml
@@ -0,0 +1,57 @@
+
+
+
+4.0.0
+
+adapter-dataapi
+jar
+
+
+ mvn-defaults
+ io.nosqlbench
+ ${revision}
+ ../../mvn-defaults
+
+
+${project.artifactId}
+
+ An nosqlbench adapter driver module for the DataStax Data API
+
+
+
+
+
+ io.nosqlbench
+ nb-annotations
+ ${revision}
+ compile
+
+
+ io.nosqlbench
+ adapters-api
+ ${revision}
+ compile
+
+
+ com.datastax.astra
+ astra-db-java
+ 1.0.0
+
+
+
+
+
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiDriverAdapter.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiDriverAdapter.java
new file mode 100644
index 000000000..8c927784e
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiDriverAdapter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024 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;
+
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapters.api.activityimpl.OpMapper;
+import io.nosqlbench.adapters.api.activityimpl.uniform.BaseDriverAdapter;
+import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter;
+import io.nosqlbench.nb.annotations.Service;
+import io.nosqlbench.nb.api.components.core.NBComponent;
+import io.nosqlbench.nb.api.config.standard.NBConfigModel;
+import io.nosqlbench.nb.api.config.standard.NBConfiguration;
+import io.nosqlbench.nb.api.labels.NBLabels;
+
+import java.util.function.Function;
+
+@Service(value = DriverAdapter.class, selector = "dataapi")
+public class DataApiDriverAdapter extends BaseDriverAdapter {
+ public DataApiDriverAdapter(NBComponent parent, NBLabels childLabels) {
+ super(parent, childLabels);
+ }
+
+ @Override
+ public OpMapper getOpMapper() {
+ return new DataApiOpMapper(this);
+ }
+
+ @Override
+ public Function getSpaceInitializer(NBConfiguration cfg) {
+ return (s) -> new DataApiSpace(s, cfg);
+ }
+
+ @Override
+ public NBConfigModel getConfigModel() {
+ return super.getConfigModel().add(DataApiSpace.getConfigModel());
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiDriverAdapterLoader.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiDriverAdapterLoader.java
new file mode 100644
index 000000000..71f4e8049
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiDriverAdapterLoader.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024 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;
+
+import io.nosqlbench.adapter.diag.DriverAdapterLoader;
+import io.nosqlbench.nb.annotations.Service;
+import io.nosqlbench.nb.api.components.core.NBComponent;
+import io.nosqlbench.nb.api.labels.NBLabels;
+
+@Service(value = DriverAdapterLoader.class, selector = "dataapi")
+public class DataApiDriverAdapterLoader implements DriverAdapterLoader {
+ @Override
+ public DataApiDriverAdapter load(NBComponent parent, NBLabels childLabels) {
+ return new DataApiDriverAdapter(parent, childLabels);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiFindVectorFilterOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiFindVectorFilterOpDispenser.java
new file mode 100644
index 000000000..e6cfe4b5d
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiFindVectorFilterOpDispenser.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 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;
+
+import com.datastax.astra.client.Database;
+import com.datastax.astra.client.model.Filter;
+import com.datastax.astra.client.model.FindOptions;
+import com.datastax.astra.client.model.Projection;
+import com.datastax.astra.client.model.Sort;
+import io.nosqlbench.adapter.dataapi.opdispensers.DataApiOpDispenser;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiFindVectorFilterOp;
+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 DataApiFindVectorFilterOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiFindVectorFilterOpDispenser.class);
+ private final LongFunction opFunction;
+ public DataApiFindVectorFilterOpDispenser(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();
+ float[] vector = getVectorValues(op, l);
+ Filter filter = getFilterFromOp(op, l);
+ int limit = getLimit(op, l);
+ return new DataApiFindVectorFilterOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ vector,
+ limit,
+ filter
+ );
+ };
+ }
+
+ private int getLimit(ParsedOp op, long l) {
+ return op.getConfigOr("limit", 100, l);
+ }
+
+ private FindOptions getFindOptions(ParsedOp op, long l) {
+ FindOptions options = new FindOptions();
+ Sort sort = getSortFromOp(op, l);
+ float[] vector = getVectorValues(op, l);
+ if (sort != null) {
+ options = vector != null ? options.sort(vector, sort) : options.sort(sort);
+ } else if (vector != null) {
+ options = options.sort(vector);
+ }
+ Projection[] projection = getProjectionFromOp(op, l);
+ if (projection != null) {
+ options = options.projection(projection);
+ }
+ options.setIncludeSimilarity(true);
+ return options;
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
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
new file mode 100644
index 000000000..190b6f79f
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiOpMapper.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 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;
+
+import io.nosqlbench.adapter.dataapi.opdispensers.*;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiOpType;
+import io.nosqlbench.adapters.api.activityimpl.OpDispenser;
+import io.nosqlbench.adapters.api.activityimpl.OpMapper;
+import io.nosqlbench.adapters.api.templating.ParsedOp;
+import io.nosqlbench.engine.api.templating.TypeAndTarget;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class DataApiOpMapper implements OpMapper {
+ private static final Logger logger = LogManager.getLogger(DataApiOpMapper.class);
+ private final DataApiDriverAdapter adapter;
+
+ public DataApiOpMapper(DataApiDriverAdapter dataApiDriverAdapter) {
+ this.adapter = dataApiDriverAdapter;
+ }
+
+ @Override
+ public OpDispenser extends DataApiBaseOp> apply(ParsedOp op) {
+ TypeAndTarget typeAndTarget = op.getTypeAndTarget(
+ DataApiOpType.class,
+ String.class,
+ "type",
+ "collection"
+ );
+ logger.debug(() -> "Using '" + typeAndTarget.enumId + "' op type for op template '" + op.getName() + "'");
+ return switch (typeAndTarget.enumId) {
+ case create_collection -> new DataApiCreateCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case insert_many -> new DataApiInsertManyOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case insert_one -> new DataApiInsertOneOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case insert_one_vector -> new DataApiInsertOneVectorOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case find -> new DataApiFindOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case find_one -> new DataApiFindOneOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case find_one_and_delete -> new DataApiFindOneAndDeleteOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case find_one_and_update -> new DataApiFindOneAndUpdateOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case find_vector -> new DataApiFindVectorOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case find_vector_filter -> new DataApiFindVectorFilterOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case update_one -> new DataApiUpdateOneOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case update_many -> new DataApiUpdateManyOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case delete_one -> new DataApiDeleteOneOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case delete_many -> new DataApiDeleteManyOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ case delete_collection -> new DataApiDropCollectionOpDispenser(adapter, op, typeAndTarget.targetFunction);
+ };
+ }
+}
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
new file mode 100644
index 000000000..e1cd61d30
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/DataApiSpace.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2024 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;
+
+import com.datastax.astra.client.DataAPIClient;
+import com.datastax.astra.client.Database;
+import io.nosqlbench.nb.api.config.standard.ConfigModel;
+import io.nosqlbench.nb.api.config.standard.NBConfigModel;
+import io.nosqlbench.nb.api.config.standard.NBConfiguration;
+import io.nosqlbench.nb.api.config.standard.Param;
+import io.nosqlbench.nb.api.errors.BasicError;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Optional;
+
+public class DataApiSpace {
+ private final static Logger logger = LogManager.getLogger(DataApiSpace.class);
+ private final NBConfiguration config;
+ private final String name;
+ private String astraToken;
+ private String astraApiEndpoint;
+ private DataAPIClient dataAPIClient;
+ private Database database;
+ private String namespace;
+
+ public DataApiSpace(String name, NBConfiguration cfg) {
+ this.config = cfg;
+ this.name = name;
+ setToken();
+ setApiEndpoint();
+ setNamespace();
+ createClient();
+ }
+
+ public DataAPIClient getDataAPIClient() {
+ return dataAPIClient;
+ }
+
+ public Database getDatabase() {
+ return database;
+ }
+
+ private void createClient() {
+ this.dataAPIClient = new DataAPIClient(astraToken);
+ if (namespace != null) {
+ this.database = dataAPIClient.getDatabase(astraApiEndpoint, namespace);
+ } else {
+ this.database = dataAPIClient.getDatabase(astraApiEndpoint);
+ }
+ }
+
+ private void setApiEndpoint() {
+ Optional epConfig = config.getOptional("astraApiEndpoint");
+ Optional epFileConfig = config.getOptional("astraApiEndpointFile");
+ if (epConfig.isPresent() && epFileConfig.isPresent()) {
+ throw new BasicError("You can only configure one of astraApiEndpoint or astraApiEndpointFile");
+ }
+ if (epConfig.isEmpty() && epFileConfig.isEmpty()) {
+ throw new BasicError("You must configure one of astraApiEndpoint or astraApiEndpointFile");
+ }
+ epFileConfig
+ .map(Path::of)
+ .map(p -> {
+ try {
+ return Files.readString(p);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ })
+ .map(String::trim)
+ .ifPresent(ep -> this.astraApiEndpoint = ep);
+ epConfig.ifPresent(ep -> this.astraApiEndpoint = ep);
+ }
+
+ private void setNamespace() {
+ Optional maybeNamespace = config.getOptional("namespace");
+ maybeNamespace.ifPresent(s -> this.namespace = s);
+ }
+
+ private void setToken() {
+ String tokenFileContents = null;
+ Optional tokenFilePath = config.getOptional("astraTokenFile");
+ if (tokenFilePath.isPresent()) {
+ Path path = Paths.get(tokenFilePath.get());
+ try {
+ tokenFileContents = Files.readAllLines(path).getFirst();
+ } catch (IOException e) {
+ String error = "Error while reading token from file:" + path;
+ logger.error(error, e);
+ throw new RuntimeException(e);
+ }
+ }
+ this.astraToken = (tokenFileContents != null) ? tokenFileContents : config.get("astraToken");
+ }
+
+ public static NBConfigModel getConfigModel() {
+ return ConfigModel.of(DataApiSpace.class)
+ .add(
+ Param.optional("astraTokenFile", String.class)
+ .setDescription("file to load the Astra token from")
+ )
+ .add(
+ Param.optional("astraToken", String.class)
+ .setDescription("the Astra token used to connect to the database")
+ )
+ .add(
+ Param.optional("astraApiEndpoint", String.class)
+ .setDescription("the API endpoint for the Astra database")
+ )
+ .add(
+ Param.optional("astraApiEndpointFile", String.class)
+ .setDescription("file to load the API endpoint for the Astra database")
+ )
+
+ .add(
+ Param.defaultTo("namespace", "default_namespace")
+ .setDescription("The Astra namespace to use")
+
+ )
+ .asReadOnly();
+ }
+
+}
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
new file mode 100644
index 000000000..14e30e5f1
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiCreateCollectionOpDispenser.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 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.model.CollectionOptions;
+import com.datastax.astra.client.model.SimilarityMetric;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiCreateCollectionOp;
+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 DataApiCreateCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) {
+ super(adapter, op, targetFunction);
+ this.opFunction = createOpFunction(op);
+ }
+
+ private LongFunction createOpFunction(ParsedOp op) {
+ return (l) -> {
+ CollectionOptions.CollectionOptionsBuilder optionsBldr = CollectionOptions.builder();
+ Optional> dimFunc = op.getAsOptionalFunction("dimensions", Integer.class);
+ if (dimFunc.isPresent()) {
+ LongFunction af = dimFunc.get();
+ optionsBldr.vectorDimension(af.apply(l));
+ }
+// COSINE("cosine"),
+// EUCLIDEAN("euclidean"),
+// DOT_PRODUCT("dot_product");
+ Optional> simFunc = op.getAsOptionalFunction("similarity", String.class);
+ if (simFunc.isPresent()) {
+ LongFunction sf = simFunc.get();
+ optionsBldr.vectorSimilarity(SimilarityMetric.fromValue(sf.apply(l)));
+ }
+
+ DataApiCreateCollectionOp dataApiCreateCollectionOp =
+ new DataApiCreateCollectionOp(
+ spaceFunction.apply(l).getDatabase(),
+ targetFunction.apply(l),
+ optionsBldr.build());
+
+ return dataApiCreateCollectionOp;
+ };
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+
+
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDeleteManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDeleteManyOpDispenser.java
new file mode 100644
index 000000000..0c0ce0f56
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDeleteManyOpDispenser.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024 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.Database;
+import com.datastax.astra.client.model.Filter;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiDeleteManyOp;
+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 DataApiDeleteManyOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiDeleteManyOpDispenser.class);
+ private final LongFunction opFunction;
+
+ public DataApiDeleteManyOpDispenser(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);
+
+ return new DataApiDeleteManyOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ filter
+ );
+ };
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDeleteOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDeleteOneOpDispenser.java
new file mode 100644
index 000000000..c5044a007
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDeleteOneOpDispenser.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2024 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.Database;
+import com.datastax.astra.client.model.DeleteOneOptions;
+import com.datastax.astra.client.model.Filter;
+import com.datastax.astra.client.model.Sort;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiDeleteOneOp;
+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 DataApiDeleteOneOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiDeleteOneOpDispenser.class);
+ private final LongFunction opFunction;
+
+ public DataApiDeleteOneOpDispenser(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);
+ DeleteOneOptions options = getDeleteOneOptions(op, l);
+
+ return new DataApiDeleteOneOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ filter,
+ options
+ );
+ };
+ }
+
+ private DeleteOneOptions getDeleteOneOptions(ParsedOp op, long l) {
+ DeleteOneOptions options = new DeleteOneOptions();
+ Sort sort = getSortFromOp(op, l);
+ if (sort != null) {
+ options = options.sort(sort);
+ }
+ float[] vector = getVectorFromOp(op, l);
+ if (vector != null) {
+ options = options.vector(vector);
+ }
+ return options;
+ }
+
+ private float[] getVectorFromOp(ParsedOp op, long l) {
+ return getVectorValues(op.get("vector", l));
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
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/DataApiDropCollectionOpDispenser.java
new file mode 100644
index 000000000..dd3748956
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiDropCollectionOpDispenser.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 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.DataApiDropCollectionOp;
+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) {
+ super(adapter, op, targetFunction);
+ this.opFunction = createOpFunction(op);
+ }
+
+ private LongFunction createOpFunction(ParsedOp op) {
+ return (l) -> new DataApiDropCollectionOp(
+ spaceFunction.apply(l).getDatabase(),
+ targetFunction.apply(l)
+ );
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneAndDeleteOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneAndDeleteOpDispenser.java
new file mode 100644
index 000000000..7a85f9995
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneAndDeleteOpDispenser.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024 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.Database;
+import com.datastax.astra.client.model.Filter;
+import com.datastax.astra.client.model.FindOneAndDeleteOptions;
+import com.datastax.astra.client.model.Projection;
+import com.datastax.astra.client.model.Sort;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiFindOneAndDeleteOp;
+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 DataApiFindOneAndDeleteOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiFindOneAndDeleteOpDispenser.class);
+ private final LongFunction opFunction;
+
+ public DataApiFindOneAndDeleteOpDispenser(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);
+ FindOneAndDeleteOptions options = getFindOneAndDeleteOptions(op, l);
+
+ return new DataApiFindOneAndDeleteOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ filter,
+ options
+ );
+ };
+ }
+
+ private FindOneAndDeleteOptions getFindOneAndDeleteOptions(ParsedOp op, long l) {
+ FindOneAndDeleteOptions options = new FindOneAndDeleteOptions();
+ 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 value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneAndUpdateOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneAndUpdateOpDispenser.java
new file mode 100644
index 000000000..1b2fffccd
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneAndUpdateOpDispenser.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 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.Database;
+import com.datastax.astra.client.model.Filter;
+import com.datastax.astra.client.model.Update;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiFindOneAndUpdateOp;
+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 DataApiFindOneAndUpdateOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiFindOneAndUpdateOpDispenser.class);
+ private final LongFunction opFunction;
+ public DataApiFindOneAndUpdateOpDispenser(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 = getUpdates(op, l);
+
+ return new DataApiFindOneAndUpdateOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ filter,
+ update
+ );
+ };
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneOpDispenser.java
new file mode 100644
index 000000000..687a9b91a
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOneOpDispenser.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 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.Database;
+import com.datastax.astra.client.model.Filter;
+import com.datastax.astra.client.model.FindOneOptions;
+import com.datastax.astra.client.model.Projection;
+import com.datastax.astra.client.model.Sort;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiFindOneOp;
+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 DataApiFindOneOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiFindOneOpDispenser.class);
+ private final LongFunction opFunction;
+ public DataApiFindOneOpDispenser(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);
+ FindOneOptions options = getFindOneOptions(op, l);
+ return new DataApiFindOneOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ filter,
+ options
+ );
+ };
+ }
+
+ private FindOneOptions getFindOneOptions(ParsedOp op, long l) {
+ FindOneOptions options = new FindOneOptions();
+ Sort sort = getSortFromOp(op, l);
+ float[] vector = getVectorValues(op, l);
+ if (sort != null) {
+ options = vector != null ? options.sort(vector, sort) : options.sort(sort);
+ } else if (vector != null) {
+ options = options.sort(vector);
+ }
+ Projection[] projection = getProjectionFromOp(op, l);
+ if (projection != null) {
+ options = options.projection(projection);
+ }
+ options.setIncludeSimilarity(true);
+ return options;
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOpDispenser.java
new file mode 100644
index 000000000..d615cc656
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindOpDispenser.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2024 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.Database;
+import com.datastax.astra.client.model.Filter;
+import com.datastax.astra.client.model.FindOptions;
+import com.datastax.astra.client.model.Projection;
+import com.datastax.astra.client.model.Sort;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiFindOp;
+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 DataApiFindOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiFindOpDispenser.class);
+ private final LongFunction opFunction;
+ public DataApiFindOpDispenser(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);
+ FindOptions options = getFindOptions(op, l);
+ return new DataApiFindOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ filter,
+ options
+ );
+ };
+ }
+
+ private FindOptions getFindOptions(ParsedOp op, long l) {
+ FindOptions options = new FindOptions();
+ Sort sort = getSortFromOp(op, l);
+ if (op.isDefined("vector")) {
+ float[] vector = getVectorValues(op, l);
+ if (sort != null) {
+ options = vector != null ? options.sort(vector, sort) : options.sort(sort);
+ } else if (vector != null) {
+ options = options.sort(vector);
+ }
+ }
+ Projection[] projection = getProjectionFromOp(op, l);
+ if (projection != null) {
+ options = options.projection(projection);
+ }
+ options.setIncludeSimilarity(true);
+ return options;
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindVectorOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindVectorOpDispenser.java
new file mode 100644
index 000000000..5aa65f912
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiFindVectorOpDispenser.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024 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.Database;
+import com.datastax.astra.client.model.FindOptions;
+import com.datastax.astra.client.model.Projection;
+import com.datastax.astra.client.model.Sort;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiFindVectorOp;
+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 DataApiFindVectorOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiFindVectorOpDispenser.class);
+ private final LongFunction opFunction;
+ public DataApiFindVectorOpDispenser(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();
+ float[] vector = getVectorValues(op, l);
+ int limit = getLimit(op, l);
+ return new DataApiFindVectorOp(
+ db,
+ db.getCollection(targetFunction.apply(l)),
+ vector,
+ limit
+ );
+ };
+ }
+
+ private int getLimit(ParsedOp op, long l) {
+ return op.getConfigOr("limit", 100, l);
+ }
+
+ private FindOptions getFindOptions(ParsedOp op, long l) {
+ FindOptions options = new FindOptions();
+ Sort sort = getSortFromOp(op, l);
+ float[] vector = getVectorValues(op, l);
+ if (sort != null) {
+ options = vector != null ? options.sort(vector, sort) : options.sort(sort);
+ } else if (vector != null) {
+ options = options.sort(vector);
+ }
+ Projection[] projection = getProjectionFromOp(op, l);
+ if (projection != null) {
+ options = options.projection(projection);
+ }
+ options.setIncludeSimilarity(true);
+ return options;
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiInsertManyOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiInsertManyOpDispenser.java
new file mode 100644
index 000000000..10788cfea
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiInsertManyOpDispenser.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024 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.model.Document;
+import com.datastax.astra.client.model.InsertManyOptions;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiInsertManyOp;
+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 DataApiInsertManyOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiInsertManyOpDispenser.class);
+ private final LongFunction opFunction;
+
+ public DataApiInsertManyOpDispenser(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 DataApiInsertManyOp(
+ spaceFunction.apply(l).getDatabase(),
+ targetFunction.apply(l),
+ documents,
+ getInsertManyOptions(op, l)
+ );
+ };
+ }
+
+ private InsertManyOptions getInsertManyOptions(ParsedOp op, long l) {
+ InsertManyOptions options = new InsertManyOptions();
+ 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()));
+ }
+ }
+ }
+ return options;
+ }
+
+ @Override
+ public DataApiBaseOp getOp(long value) {
+ return opFunction.apply(value);
+ }
+}
diff --git a/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiInsertOneOpDispenser.java b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiInsertOneOpDispenser.java
new file mode 100644
index 000000000..3c24357c2
--- /dev/null
+++ b/nb-adapters/adapter-dataapi/src/main/java/io/nosqlbench/adapter/dataapi/opdispensers/DataApiInsertOneOpDispenser.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 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.model.Document;
+import io.nosqlbench.adapter.dataapi.DataApiDriverAdapter;
+import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
+import io.nosqlbench.adapter.dataapi.ops.DataApiInsertOneOp;
+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 DataApiInsertOneOpDispenser extends DataApiOpDispenser {
+ private static final Logger logger = LogManager.getLogger(DataApiInsertOneOpDispenser.class);
+ private final LongFunction opFunction;
+
+ public DataApiInsertOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction targetFunction) {
+ super(adapter, op, targetFunction);
+ this.opFunction = createOpFunction(op);
+ }
+
+ private LongFunction createOpFunction(ParsedOp op) {
+ LongFunction