merge-up for dapi and qdrant prototypes

This commit is contained in:
Jonathan Shook
2024-05-10 19:59:21 -05:00
58 changed files with 2528 additions and 5 deletions

View File

@@ -0,0 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="SCENARIO astra DAPI dapi_novector" type="JarApplication" folderName="Astra DAPI">
<extension name="software.aws.toolkits.jetbrains.core.execution.JavaAwsConnectionExtension">
<option name="credential" />
<option name="region" />
<option name="useCurrentConnection" value="false" />
</extension>
<option name="JAR_PATH" value="$PROJECT_DIR$/nb5/target/nb5.jar" />
<option name="PROGRAM_PARAMETERS" value="astra_kv_dapi dapi_novector collection=baselines astraTokenFile=target/token astraApiEndpointFile=target/endpoint -v" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/local/dataapi" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="ALTERNATIVE_JRE_PATH" value="21" />
<method v="2" />
</configuration>
</component>

View File

@@ -0,0 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="astra DAPI rampup threads=1" type="JarApplication" folderName="Astra DAPI">
<extension name="software.aws.toolkits.jetbrains.core.execution.JavaAwsConnectionExtension">
<option name="credential" />
<option name="region" />
<option name="useCurrentConnection" value="false" />
</extension>
<option name="JAR_PATH" value="$PROJECT_DIR$/nb5/target/nb5.jar" />
<option name="PROGRAM_PARAMETERS" value="astra_kv_dapi default.rampup threads=1 astraTokenFile=target/token astraApiEndpointFile=target/endpoint -v" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/local/dataapi" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="ALTERNATIVE_JRE_PATH" value="21" />
<method v="2" />
</configuration>
</component>

View File

@@ -0,0 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="astra DAPI read" type="JarApplication" folderName="Astra DAPI">
<extension name="software.aws.toolkits.jetbrains.core.execution.JavaAwsConnectionExtension">
<option name="credential" />
<option name="region" />
<option name="useCurrentConnection" value="false" />
</extension>
<option name="JAR_PATH" value="$PROJECT_DIR$/nb5/target/nb5.jar" />
<option name="PROGRAM_PARAMETERS" value="astra_kv_dapi default.read threads=1 astraTokenFile=target/token astraApiEndpointFile=target/endpoint -v" />
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/local/dataapi" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="ALTERNATIVE_JRE_PATH" value="21" />
<method v="2" />
</configuration>
</component>

View File

View File

@@ -0,0 +1,57 @@
<!--
~ Copyright (c) 2022-2023 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>adapter-dataapi</artifactId>
<packaging>jar</packaging>
<parent>
<artifactId>mvn-defaults</artifactId>
<groupId>io.nosqlbench</groupId>
<version>${revision}</version>
<relativePath>../../mvn-defaults</relativePath>
</parent>
<name>${project.artifactId}</name>
<description>
An nosqlbench adapter driver module for the DataStax Data API
</description>
<dependencies>
<dependency>
<groupId>io.nosqlbench</groupId>
<artifactId>nb-annotations</artifactId>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.nosqlbench</groupId>
<artifactId>adapters-api</artifactId>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.datastax.astra</groupId>
<artifactId>astra-db-java</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -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<DataApiBaseOp, DataApiSpace> {
public DataApiDriverAdapter(NBComponent parent, NBLabels childLabels) {
super(parent, childLabels);
}
@Override
public OpMapper getOpMapper() {
return new DataApiOpMapper(this);
}
@Override
public Function<String, ? extends DataApiSpace> getSpaceInitializer(NBConfiguration cfg) {
return (s) -> new DataApiSpace(s, cfg);
}
@Override
public NBConfigModel getConfigModel() {
return super.getConfigModel().add(DataApiSpace.getConfigModel());
}
}

View File

@@ -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);
}
}

View File

@@ -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<DataApiFindVectorFilterOp> opFunction;
public DataApiFindVectorFilterOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiFindVectorFilterOp> 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);
}
}

View File

@@ -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<DataApiBaseOp> {
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<DataApiOpType, String> 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);
};
}
}

View File

@@ -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<String> epConfig = config.getOptional("astraApiEndpoint");
Optional<String> 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<String> maybeNamespace = config.getOptional("namespace");
maybeNamespace.ifPresent(s -> this.namespace = s);
}
private void setToken() {
String tokenFileContents = null;
Optional<String> 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();
}
}

View File

@@ -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<DataApiCreateCollectionOp> opFunction;
public DataApiCreateCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiCreateCollectionOp> createOpFunction(ParsedOp op) {
return (l) -> {
CollectionOptions.CollectionOptionsBuilder optionsBldr = CollectionOptions.builder();
Optional<LongFunction<Integer>> dimFunc = op.getAsOptionalFunction("dimensions", Integer.class);
if (dimFunc.isPresent()) {
LongFunction<Integer> af = dimFunc.get();
optionsBldr.vectorDimension(af.apply(l));
}
// COSINE("cosine"),
// EUCLIDEAN("euclidean"),
// DOT_PRODUCT("dot_product");
Optional<LongFunction<String>> simFunc = op.getAsOptionalFunction("similarity", String.class);
if (simFunc.isPresent()) {
LongFunction<String> 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);
}
}

View File

@@ -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<DataApiDeleteManyOp> opFunction;
public DataApiDeleteManyOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiDeleteManyOp> 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);
}
}

View File

@@ -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<DataApiDeleteOneOp> opFunction;
public DataApiDeleteOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiDeleteOneOp> 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);
}
}

View File

@@ -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<DataApiDropCollectionOp> opFunction;
public DataApiDropCollectionOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiDropCollectionOp> createOpFunction(ParsedOp op) {
return (l) -> new DataApiDropCollectionOp(
spaceFunction.apply(l).getDatabase(),
targetFunction.apply(l)
);
}
@Override
public DataApiBaseOp getOp(long value) {
return opFunction.apply(value);
}
}

View File

@@ -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<DataApiFindOneAndDeleteOp> opFunction;
public DataApiFindOneAndDeleteOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiFindOneAndDeleteOp> 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);
}
}

View File

@@ -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<DataApiFindOneAndUpdateOp> opFunction;
public DataApiFindOneAndUpdateOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiFindOneAndUpdateOp> 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);
}
}

View File

@@ -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<DataApiFindOneOp> opFunction;
public DataApiFindOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiFindOneOp> 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);
}
}

View File

@@ -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<DataApiFindOp> opFunction;
public DataApiFindOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiFindOp> 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);
}
}

View File

@@ -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<DataApiFindVectorOp> opFunction;
public DataApiFindVectorOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiFindVectorOp> 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);
}
}

View File

@@ -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<DataApiInsertManyOp> opFunction;
public DataApiInsertManyOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiInsertManyOp> createOpFunction(ParsedOp op) {
return (l) -> {
List<Document> 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<LongFunction<Map>> optionsFunction = op.getAsOptionalFunction("options", Map.class);
if (optionsFunction.isPresent()) {
Map<String, String> optionFields = optionsFunction.get().apply(l);
for(Map.Entry<String,String> 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);
}
}

View File

@@ -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<DataApiInsertOneOp> opFunction;
public DataApiInsertOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiInsertOneOp> createOpFunction(ParsedOp op) {
LongFunction<Map> docMapFunc = op.getAsRequiredFunction("document", Map.class);
LongFunction<Document> docFunc = (long m) -> new Document(docMapFunc.apply(m));
return (l) -> {
return new DataApiInsertOneOp(
spaceFunction.apply(l).getDatabase(),
targetFunction.apply(l),
docFunc.apply(l)
);
};
}
@Override
public DataApiBaseOp getOp(long value) {
return opFunction.apply(value);
}
}

View File

@@ -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.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.adapter.dataapi.ops.DataApiInsertOneVectorOp;
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 DataApiInsertOneVectorOpDispenser extends DataApiOpDispenser {
private static final Logger logger = LogManager.getLogger(DataApiInsertOneVectorOpDispenser.class);
private final LongFunction<DataApiInsertOneVectorOp> opFunction;
public DataApiInsertOneVectorOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
this.opFunction = createOpFunction(op);
}
private LongFunction<DataApiInsertOneVectorOp> createOpFunction(ParsedOp op) {
LongFunction<Map> docMapFunc = op.getAsRequiredFunction("document", Map.class);
LongFunction<Document> docFunc = (long m) -> new Document(docMapFunc.apply(m));
LongFunction<float[]> vectorF= op.getAsRequiredFunction("vector", float[].class);
return (l) -> {
return new DataApiInsertOneVectorOp(
spaceFunction.apply(l).getDatabase(),
targetFunction.apply(l),
docFunc.apply(l),
vectorF.apply(l)
);
};
}
@Override
public DataApiBaseOp getOp(long value) {
return opFunction.apply(value);
}
}

View File

@@ -0,0 +1,191 @@
/*
* 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.*;
import io.nosqlbench.adapter.dataapi.DataApiSpace;
import io.nosqlbench.adapter.dataapi.ops.DataApiBaseOp;
import io.nosqlbench.adapters.api.activityimpl.BaseOpDispenser;
import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter;
import io.nosqlbench.adapters.api.templating.ParsedOp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.LongFunction;
public abstract class DataApiOpDispenser extends BaseOpDispenser<DataApiBaseOp, DataApiSpace> {
protected final LongFunction<String> targetFunction;
protected final LongFunction<DataApiSpace> spaceFunction;
protected DataApiOpDispenser(DriverAdapter<? extends DataApiBaseOp, DataApiSpace> adapter, ParsedOp op,
LongFunction<String> targetFunction) {
super(adapter, op);
this.targetFunction = targetFunction;
this.spaceFunction = adapter.getSpaceFunc(op);
}
protected Sort getSortFromOp(ParsedOp op, long l) {
Sort sort = null;
Optional<LongFunction<Map>> sortFunction = op.getAsOptionalFunction("sort", Map.class);
if (sortFunction.isPresent()) {
Map<String,Object> sortFields = sortFunction.get().apply(l);
String sortOrder = sortFields.get("type").toString();
String sortField = sortFields.get("field").toString();
switch(sortOrder) {
case "asc" -> sort = Sorts.ascending(sortField);
case "desc" -> sort = Sorts.descending(sortField);
}
}
return sort;
}
protected Filter getFilterFromOp(ParsedOp op, long l) {
// TODO: Clarify 'filter' vs 'filters' or whether to support both uniformly
Filter filter = null;
Optional<LongFunction<List>> filterFunction = op.getAsOptionalFunction("filters", List.class).or(
() -> op.getAsOptionalFunction("filter",List.class)
);
if (filterFunction.isPresent()) {
List<Map<String,Object>> filters = filterFunction.get().apply(l);
List<Filter> andFilterList = new ArrayList<>();
List<Filter> orFilterList = new ArrayList<>();
for (Map<String,Object> filterFields : filters) {
switch ((String)filterFields.get("conjunction")) {
case "and" -> {
switch (filterFields.get("operator").toString()) {
case "lt" ->
andFilterList.add(Filters.lt(filterFields.get("field").toString(), (long) filterFields.get("value")));
case "gt" ->
andFilterList.add(Filters.gt(filterFields.get("field").toString(), (long) filterFields.get("value")));
case "eq" ->
andFilterList.add(Filters.eq(filterFields.get("field").toString(), filterFields.get("value")));
default -> logger.error(() -> "Operation " + filterFields.get("operator") + " not supported");
}
}
case "or" -> {
switch (filterFields.get("operator").toString()) {
case "lt" ->
orFilterList.add(Filters.lt(filterFields.get("field").toString(), (long) filterFields.get("value")));
case "gt" ->
orFilterList.add(Filters.gt(filterFields.get("field").toString(), (long) filterFields.get("value")));
case "eq" ->
orFilterList.add(Filters.eq(filterFields.get("field").toString(), filterFields.get("value")));
default -> logger.error(() -> "Operation " + filterFields.get("operator") + " not supported");
}
}
default -> logger.error(() -> "Conjunction " + filterFields.get("conjunction") + " not supported");
}
}
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 Update getUpdates(ParsedOp op, long l) {
Update update = new Update();
Optional<LongFunction<Map>> updatesFunction = op.getAsOptionalFunction("updates", Map.class);
if (updatesFunction.isPresent()) {
Map<String, Object> updates = updatesFunction.get().apply(l);
for (Map.Entry<String, Object> entry : updates.entrySet()) {
if (entry.getKey().equalsIgnoreCase("update")) {
Map<String, Object> updateFields = (Map<String, Object>) 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(), (double) updateFields.get("value"));
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"));
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");
}
}
}
return update;
}
protected float[] getVectorValues(ParsedOp op, long l) {
Object rawVectorValues = op.get("vector", l);
return getVectorValues(rawVectorValues);
}
protected float[] getVectorValues(Object rawVectorValues) {
float[] floatValues;
if (rawVectorValues instanceof float[] f) {
return f;
}
if (rawVectorValues instanceof String) {
String[] rawValues = (((String) rawVectorValues).split(","));
floatValues = new float[rawValues.length];
for (int i = 0; i < rawValues.length; i++) {
floatValues[i] = Float.parseFloat(rawValues[i]);
}
} else if (rawVectorValues instanceof List) {
return getVectorValuesList(rawVectorValues);
} else {
throw new RuntimeException("Invalid type specified for values (type: " + rawVectorValues.getClass().getSimpleName() + "), values: " + rawVectorValues.toString());
}
return floatValues;
}
protected float[] getVectorValuesList(Object rawVectorValues) {
float[] vectorValues = null;
List<Object> vectorValuesList = (List<Object>) rawVectorValues;
vectorValues = new float[vectorValuesList.size()];
for (int i = 0; i < vectorValuesList.size(); i++) {
vectorValues[i] = Float.parseFloat(vectorValuesList.get(i).toString());
}
return vectorValues;
}
protected Projection[] getProjectionFromOp(ParsedOp op, long l) {
Projection[] projection = null;
Optional<LongFunction<Map>> projectionFunction = op.getAsOptionalFunction("projection", Map.class);
if (projectionFunction.isPresent()) {
Map<String,List<String>> projectionFields = projectionFunction.get().apply(l);
for (Map.Entry<String,List<String>> field : projectionFields.entrySet()) {
List<String> 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 = Projections.include(sb.toString());
} else if (field.getKey().equalsIgnoreCase("exclude")) {
projection = Projections.exclude(sb.toString());
} else {
logger.error("Projection " + field + " not supported");
}
}
}
return projection;
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.adapters.api.templating.ParsedOp;
import java.util.function.LongFunction;
public class DataApiUpdateManyOpDispenser extends DataApiOpDispenser {
public DataApiUpdateManyOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
}
@Override
public DataApiBaseOp getOp(long value) {
return null;
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.adapters.api.templating.ParsedOp;
import java.util.function.LongFunction;
public class DataApiUpdateOneOpDispenser extends DataApiOpDispenser {
public DataApiUpdateOneOpDispenser(DataApiDriverAdapter adapter, ParsedOp op, LongFunction<String> targetFunction) {
super(adapter, op, targetFunction);
}
@Override
public DataApiBaseOp getOp(long value) {
return null;
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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.ops;
import com.datastax.astra.client.Database;
import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.CycleOp;
public abstract class DataApiBaseOp implements CycleOp {
protected final Database db;
public DataApiBaseOp(Database db) {
this.db = db;
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.ops;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.CollectionOptions;
public class DataApiCreateCollectionOp extends DataApiBaseOp {
private final String collectionName;
private final CollectionOptions options;
public DataApiCreateCollectionOp(Database db, String collectionName, CollectionOptions options) {
super(db);
this.collectionName = collectionName;
this.options = options;
}
@Override
public Object apply(long value) {
return db.createCollection(collectionName, options);
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Filter;
public class DataApiDeleteManyOp extends DataApiBaseOp {
private final Collection collection;
private final Filter filter;
public DataApiDeleteManyOp(Database db, Collection collection, Filter filter) {
super(db);
this.collection = collection;
this.filter = filter;
}
@Override
public Object apply(long value) {
return collection.deleteMany(filter);
}
}

View File

@@ -0,0 +1,40 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.DeleteOneOptions;
import com.datastax.astra.client.model.Filter;
public class DataApiDeleteOneOp extends DataApiBaseOp {
private final Collection collection;
private final Filter filter;
private final DeleteOneOptions options;
public DataApiDeleteOneOp(Database db, Collection collection, Filter filter, DeleteOneOptions options) {
super(db);
this.collection = collection;
this.filter = filter;
this.options = options;
}
@Override
public Object apply(long value) {
return collection.deleteOne(filter, options);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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.ops;
import com.datastax.astra.client.Database;
public class DataApiDropCollectionOp extends DataApiBaseOp {
private final String collectionName;
public DataApiDropCollectionOp(Database db, String collectionName) {
super(db);
this.collectionName = collectionName;
}
@Override
public Object apply(long value) {
Boolean exists = db.collectionExists(collectionName);
// TODO: we need to remove these from the ops when we can, because this hides additional ops which
// should be surfaced in the test definition. Condition operations should be provided with clear views
// at the workload template level
if (exists) {
db.dropCollection(collectionName);
}
return exists;
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Document;
import com.datastax.astra.client.model.Filter;
import com.datastax.astra.client.model.FindOneAndDeleteOptions;
public class DataApiFindOneAndDeleteOp extends DataApiBaseOp {
private final Collection<Document> collection;
private final Filter filter;
private final FindOneAndDeleteOptions options;
public DataApiFindOneAndDeleteOp(Database db, Collection<Document> collection, Filter filter, FindOneAndDeleteOptions options) {
super(db);
this.collection = collection;
this.filter = filter;
this.options = options;
}
@Override
public Object apply(long value) {
return collection.findOneAndDelete(filter, options);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.*;
public class DataApiFindOneAndUpdateOp extends DataApiBaseOp {
private final Collection<Document> collection;
private final Filter filter;
private final Update update;
public DataApiFindOneAndUpdateOp(Database db, Collection<Document> collection, Filter filter, Update update) {
super(db);
this.collection = collection;
this.filter = filter;
this.update = update;
}
@Override
public Object apply(long value) {
return collection.findOneAndUpdate(filter, update);
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Document;
import com.datastax.astra.client.model.Filter;
import com.datastax.astra.client.model.FindOneOptions;
public class DataApiFindOneOp extends DataApiBaseOp {
private final Collection<Document> collection;
private final Filter filter;
private final FindOneOptions options;
public DataApiFindOneOp(Database db, Collection<Document> collection, Filter filter, FindOneOptions options) {
super(db);
this.collection = collection;
this.filter = filter;
this.options = options;
}
@Override
public Object apply(long value) {
return collection.findOne(filter, options);
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.*;
import java.util.List;
import java.util.stream.StreamSupport;
public class DataApiFindOp extends DataApiBaseOp {
private final Collection<Document> collection;
private final Filter filter;
private final FindOptions options;
public DataApiFindOp(Database db, Collection<Document> collection, Filter filter, FindOptions options) {
super(db);
this.collection = collection;
this.filter = filter;
this.options = options;
}
@Override
public List<Document> apply(long value) {
// TODO: make sure we're traversing result data
FindIterable<Document> documentStream = collection.find(filter, options);
List<Document> documents = StreamSupport.stream(documentStream.spliterator(), false).toList();
return documents;
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Document;
import com.datastax.astra.client.model.Filter;
public class DataApiFindVectorFilterOp extends DataApiBaseOp {
private final Collection<Document> collection;
private final float[] vector;
private final int limit;
private final Filter filter;
public DataApiFindVectorFilterOp(Database db, Collection<Document> collection, float[] vector, int limit, Filter filter) {
super(db);
this.collection = collection;
this.vector = vector;
this.limit = limit;
this.filter = filter;
}
@Override
public Object apply(long value) {
return collection.find(filter, vector, limit);
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.ops;
import com.datastax.astra.client.Collection;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Document;
import com.datastax.astra.client.model.Filter;
import com.datastax.astra.client.model.FindOptions;
public class DataApiFindVectorOp extends DataApiBaseOp {
private final Collection<Document> collection;
private final float[] vector;
private final int limit;
public DataApiFindVectorOp(Database db, Collection<Document> collection, float[] vector, int limit) {
super(db);
this.collection = collection;
this.vector = vector;
this.limit = limit;
}
@Override
public Object apply(long value) {
return collection.find(vector, limit);
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.ops;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Document;
import com.datastax.astra.client.model.InsertManyOptions;
import java.util.List;
public class DataApiInsertManyOp extends DataApiBaseOp {
private final List<? extends Document> documents;
private final String collectionName;
private final InsertManyOptions options;
public DataApiInsertManyOp(Database db, String collectionName, List<? extends Document> documents, InsertManyOptions options) {
super(db);
this.collectionName = collectionName;
this.documents = documents;
this.options = options;
}
@Override
public Object apply(long value) {
return db.getCollection(collectionName).insertMany(documents, options);
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.ops;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Document;
public class DataApiInsertOneOp extends DataApiBaseOp {
private final Document doc;
private final String collectionName;
public DataApiInsertOneOp(Database db, String collectionName, Document doc) {
super(db);
this.collectionName = collectionName;
this.doc = doc;
}
@Override
public Object apply(long value) {
return db.getCollection(collectionName).insertOne(doc);
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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.ops;
import com.datastax.astra.client.Database;
import com.datastax.astra.client.model.Document;
public class DataApiInsertOneVectorOp extends DataApiBaseOp {
private final Document doc;
private final String collectionName;
private float[] vector;
public DataApiInsertOneVectorOp(Database db, String collectionName, Document doc, float[] vector) {
super(db);
this.collectionName = collectionName;
this.doc = doc;
this.vector = vector;
}
@Override
public Object apply(long value) {
return db.getCollection(collectionName).insertOne(doc, vector);
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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.ops;
public enum DataApiOpType {
create_collection,
insert_many,
insert_one,
insert_one_vector,
find,
find_one,
find_one_and_delete,
find_one_and_update,
find_vector,
find_vector_filter,
update_one,
update_many,
delete_one,
delete_many,
delete_collection
}

View File

@@ -0,0 +1,193 @@
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.
TEMPLATE(cardinality,1000)
TEMPLATE(collection,keyvalue)
TEMPLATE(dimensions,1536)
TEMPLATE(similarity,COSINE)
TEMPLATE(keycount,TEMPLATE(cardinality))
TEMPLATE(valuecount,TEMPLATE(cardinality))
scenarios:
dapi_novector:
schema: run driver=dataapi tags==block:schema threads==1 cycles==UNDEF
rampup: >-
run driver=dataapi tags==block:rampup
cycles===TEMPLATE(rampup-cycles,TEMPLATE(cardinality))
threads=auto errors=count
find_key: >-
run driver=dataapi tags==block:find_key
cycles===TEMPLATE(main-cycles,1000)
threads=auto errors=count
dapi_vector_d1536:
schema_vector: run driver=dataapi tags==block:schema_vector threads==1 cycles==UNDEF
rampup_vector: >-
run driver=dataapi tags==block:rampup_vector
cycles===TEMPLATE(rampup-cycles,TEMPLATE(cardinality))
threads=auto errors=count
find_key_vector: >-
run driver=dataapi tags==block:find_key_vector
cycles===TEMPLATE(main-cycles,TEMPLATE(cardinality))
threads=auto errors=count
# kv_dapi:
# kv_dapi_schema: run driver=http tags==block:schema threads==1 cycles==UNDEF
# kv_dapi_rampup: run driver=http tags==block:rampup cycles===TEMPLATE(rampup-cycles,10000000) threads=auto
# kv_dapi_main: run driver=http tags==block:"main.*" cycles===TEMPLATE(main-cycles,10000000) threads=auto
# basic_check:
# schema: run driver=http tags==block:schema threads==1 cycles==UNDEF
# rampup: run driver=http tags==block:rampup cycles===TEMPLATE(rampup-cycles,10) threads=auto
# main: run driver=http tags==block:"main.*" cycles===TEMPLATE(main-cycles,10) threads=auto
bindings:
# To enable an optional weighted set of hosts in place of a load balancer
# Examples
# single host: jsonapi_host=host1
# multiple hosts: jsonapi_host=host1,host2,host3
# multiple weighted hosts: jsonapi_host=host1:3,host2:7
weighted_hosts: WeightedStrings('TEMPLATE(jsonapi_host,TEMPLATE(stargate_host,localhost))')
seq_key: Mod(TEMPLATE(keycount)); ToString() -> String
# seq_key: Mod(TEMPLATE(keycount,50000000000L));
seq_value: Hash(); Mod(TEMPLATE(valuecount)); ToString() -> String
# rw_key: TEMPLATE(keydist,Uniform(0,50000000000L));
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)
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:
ops:
delete_collection_op:
delete_collection: "TEMPLATE(collection)"
create_collection_op:
create_collection: "TEMPLATE(collection)"
# separate these cases later, when you can recreate the same collection name with/without vector support
schema_vector:
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:
ops:
insert_one_op:
insert_one: "TEMPLATE(collection)"
document:
_id: "{seq_key}"
value: "{seq_value}"
rampup_vector:
ops:
insert_one_op_v:
insert_one_vector: "TEMPLATE(collection)_v"
document:
_id: "{seq_key}"
value: "{seq_value}"
vector: "{vector_value}"
# rampup-uuid:
# ops:
# insert_one_op:
# insert-one: "TEMPLATE(collection)"
# document:
# value: "{seq_value}"
find_key:
params:
ratio: 5
ops:
find_op:
find: "TEMPLATE(collection)"
filters:
- conjunction: "and"
operator: "lt"
field: "_id"
value: "{rw_key_num}"
vector: "{vector_value}"
find_key_vector:
params:
ratio: 5
ops:
find_op_v:
find_vector_filter: "TEMPLATE(collection)"
filters:
- conjunction: "and"
operator: "lt"
field: "_id"
value: "{rw_key_num}"
vector: "{vector_value}"
#
# rampup_with_vector_uuid:
# ops:
# insert_one_op:
# insert_one: "TEMPLATE(collection)"
# document:
# value: "{seq_value}"
# vector: "{vector_value}"
#
# main_read_with_vector:
# ops:
# find_op:
# find: "TEMPLATE(collection)"
# filter:
# _id: "{rw_key}"
#
# 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}"

View File

@@ -0,0 +1,11 @@
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"

View File

@@ -0,0 +1,18 @@
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"

View File

@@ -0,0 +1,13 @@
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"

View File

@@ -0,0 +1,9 @@
scenarios:
default:
drop_collection: run driver=dataapi tags==blocks:drop_collection cycles=1
blocks:
drop_collection:
ops:
op1:
drop_collection: "collectionName"

View File

@@ -0,0 +1,26 @@
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"

View File

@@ -0,0 +1,26 @@
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"

View File

@@ -0,0 +1,25 @@
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"

View File

@@ -0,0 +1,17 @@
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}"

View File

@@ -0,0 +1,10 @@
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}"

View File

@@ -0,0 +1,11 @@
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"

View File

@@ -141,6 +141,20 @@
</dependencies>
</profile>
<profile>
<id>adapter-dataapi-include</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>io.nosqlbench</groupId>
<artifactId>adapter-dataapi</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>adapter-dynamodb-include</id>
<activation>
@@ -186,7 +200,7 @@
<profile>
<id>adapter-s4j-include</id>
<activation>
<activeByDefault>true</activeByDefault>
<activeByDefault>false</activeByDefault>
</activation>
<dependencies>
<dependency>
@@ -252,6 +266,7 @@
</dependency>
</dependencies>
</profile>
</profiles>
</project>

View File

@@ -1,5 +1,5 @@
<!--
~ Copyright (c) 2022-2024 nosqlbench
~ Copyright (c) 2022-2023 nosqlbench
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -147,7 +147,7 @@
<profile>
<id>adapter-s4j-module</id>
<activation>
<activeByDefault>true</activeByDefault>
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<module>adapter-s4j</module>
@@ -174,6 +174,16 @@
</modules>
</profile>
<profile>
<id>adapter-dataapi-module</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>adapter-dataapi</module>
</modules>
</profile>
<profile>
<id>adapter-qdrant-module</id>
<activation>

View File

@@ -178,7 +178,7 @@ public class NBConfiguration {
}
}
} else {
throw new NBConfigError("Parameter was not found for " + Arrays.toString(names) + ".");
throw new NBConfigError("Parameter definition was not found for " + Arrays.toString(names) + ".");
}
}
if (o == null) {

View File

@@ -136,6 +136,9 @@ public class Param<T> {
* @return
*/
public static <V> Param<V> defaultTo(String name, V defaultValue) {
if (defaultValue instanceof Class clazz) {
throw new RuntimeException("This is not a supported type.");
}
return new Param<V>(List.of(name), (Class<V>) defaultValue.getClass(), null, true, defaultValue, null);
}

View File

@@ -28,6 +28,22 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ParsedTemplateMapTest {
// @Test
// public void testBindpointTypes() {
// ParsedTemplateMap ptm = new ParsedTemplateMap(
// "name1",
// Map.of(
// "field1","{binding1}",
// "field2", " {binding2}"
// ),
// Map.of(
// "binding1","TestingStringFunc('b1')",
// "binding2","TestingStringFunc('b2')"
// ),
// List.of(Map.of()));
//
// }
@Test
public void testParsedTemplateMap() {
ParsedTemplateMap ptm = new ParsedTemplateMap("name1", Map.of("string1", "string2"), Map.of(), List.of());

View File

@@ -1,4 +1,4 @@
<!--
/<!--
~ Copyright (c) 2022-2023 nosqlbench
~
~ Licensed under the Apache License, Version 2.0 (the "License");