From f360c8592d9c97eac3fe9e47d3c7b16058baadbc Mon Sep 17 00:00:00 2001 From: Jeffrey Carpenter Date: Tue, 14 Feb 2023 15:28:31 -0700 Subject: [PATCH 1/3] adding nosqlbench test scripts --- docker-compose/docker-compose-dev-mode.yml | 2 +- docker-compose/docker-compose.yml | 2 +- docker-compose/start_dse_68.sh | 4 +- docker-compose/start_dse_68_dev_mode.sh | 4 +- nosqlbench/http-jsonapi-crud-basic.md | 64 ++ nosqlbench/http-jsonapi-crud-basic.yaml | 207 ++++++ nosqlbench/http-jsonapi-crud-dataset.md | 41 ++ nosqlbench/http-jsonapi-crud-dataset.yaml | 116 ++++ nosqlbench/http-jsonapi-keyvalue.yaml | 136 ++++ nosqlbench/http-jsonapi-search-advanced.md | 65 ++ nosqlbench/http-jsonapi-search-advanced.yaml | 625 +++++++++++++++++++ nosqlbench/http-jsonapi-search-basic.md | 63 ++ nosqlbench/http-jsonapi-search-basic.yaml | 353 +++++++++++ 13 files changed, 1676 insertions(+), 6 deletions(-) create mode 100644 nosqlbench/http-jsonapi-crud-basic.md create mode 100644 nosqlbench/http-jsonapi-crud-basic.yaml create mode 100644 nosqlbench/http-jsonapi-crud-dataset.md create mode 100644 nosqlbench/http-jsonapi-crud-dataset.yaml create mode 100644 nosqlbench/http-jsonapi-keyvalue.yaml create mode 100644 nosqlbench/http-jsonapi-search-advanced.md create mode 100644 nosqlbench/http-jsonapi-search-advanced.yaml create mode 100644 nosqlbench/http-jsonapi-search-basic.md create mode 100644 nosqlbench/http-jsonapi-search-basic.yaml diff --git a/docker-compose/docker-compose-dev-mode.yml b/docker-compose/docker-compose-dev-mode.yml index 4a268aaf40..d8b3c39d8f 100644 --- a/docker-compose/docker-compose-dev-mode.yml +++ b/docker-compose/docker-compose-dev-mode.yml @@ -34,7 +34,7 @@ services: networks: - stargate ports: - - "8180:8080" + - "8080:8080" mem_limit: 2G environment: - QUARKUS_GRPC_CLIENTS_BRIDGE_HOST=coordinator diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml index 4373d2bbbc..cf8d660645 100644 --- a/docker-compose/docker-compose.yml +++ b/docker-compose/docker-compose.yml @@ -98,7 +98,7 @@ services: networks: - stargate ports: - - "8180:8080" + - "8080:8080" mem_limit: 2G environment: - QUARKUS_GRPC_CLIENTS_BRIDGE_HOST=coordinator diff --git a/docker-compose/start_dse_68.sh b/docker-compose/start_dse_68.sh index e0e0b37b3a..c9ba3d5db0 100755 --- a/docker-compose/start_dse_68.sh +++ b/docker-compose/start_dse_68.sh @@ -35,6 +35,6 @@ export DSETAG export SGTAG export JSONTAG -echo "Running with DSE $DSETAG, Stargate $SGTAG, JSON API $JSON" +echo "Running with DSE $DSETAG, Stargate $SGTAG, JSON API $JSONTAG" -docker-compose up -d +docker-compose up -d --wait diff --git a/docker-compose/start_dse_68_dev_mode.sh b/docker-compose/start_dse_68_dev_mode.sh index 8b2734c4a9..8e0b480127 100755 --- a/docker-compose/start_dse_68_dev_mode.sh +++ b/docker-compose/start_dse_68_dev_mode.sh @@ -35,6 +35,6 @@ export DSETAG export SGTAG export JSONTAG -echo "Running with DSE $DSETAG, Stargate $SGTAG, JSON API $JSON" +echo "Running with DSE $DSETAG, Stargate $SGTAG, JSON API $JSONTAG" -docker-compose -f docker-compose-dev-mode.yml up -d \ No newline at end of file +docker-compose -f docker-compose-dev-mode.yml up -d --wait \ No newline at end of file diff --git a/nosqlbench/http-jsonapi-crud-basic.md b/nosqlbench/http-jsonapi-crud-basic.md new file mode 100644 index 0000000000..145d95ede5 --- /dev/null +++ b/nosqlbench/http-jsonapi-crud-basic.md @@ -0,0 +1,64 @@ +# JSON API CRUD Basic + +## Description + +The JSON API CRUD Basic workflow targets Stargate's JSON API using generated JSON documents. +The documents used are sharing the same structure and are approximately half a kilobyte in size each: + +* each document has 13 leaf values, with a maximum depth of 3 +* there is at least one `string`, `boolean`, `number` and `null` leaf +* there is one array with `double` values and one with `string` values +* there is one empty array and one empty map + +The example JSON looks like: + +```json +{ + "user_id":"56fd76f6-081d-401a-85eb-b1d9e5bba058", + "created_on":1476743286, + "gender":"F", + "full_name":"Andrew Daniels", + "married":true, + "address":{ + "primary":{ + "cc":"IO", + "city":"Okmulgee" + }, + "secondary":{ + + } + }, + "coordinates":[ + 64.65964627052323, + -122.35334535072856 + ], + "children":[ + + ], + "friends":[ + "3df498b1-9568-4584-96fd-76f6081da01a" + ], + "debt":null +} +``` + +In contrast to other workflows, this one is not split into ramp-up and main phases. +Instead, there is only the main phase with 4 different load types (write, read, update and delete). + +## Named Scenarios + +### default + +The default scenario for http-jsonapi-crud-basic.yaml runs each type of the main phase sequentially: write, read, update and delete. +This means that setting cycles for each of the phases should be done using the: `write-cycles`, `read-cycles`, `update-cycles` and `delete-cycles`. +The default value for all 4 cycles variables is the amount of documents to process (see [Workload Parameters](#workload-parameters)). + +Note that error handling is set to `errors=timer,warn`, which means that in case of HTTP errors the scenario is not stopped. + +## Workload Parameters + +- `docscount` - the number of documents to process in each step of a scenario (default: `10_000_000`) + +Note that if number of documents is higher than `read-cycles` you would experience misses, which will result in `HTTP 404` and smaller latencies. + + diff --git a/nosqlbench/http-jsonapi-crud-basic.yaml b/nosqlbench/http-jsonapi-crud-basic.yaml new file mode 100644 index 0000000000..bd2da2ec8a --- /dev/null +++ b/nosqlbench/http-jsonapi-crud-basic.yaml @@ -0,0 +1,207 @@ +min_version: "4.17.15" + +# nb5 -v run driver=http yaml=http-jsonapi-crud-basic jsonapi_host=my_jsonapi_host auth_token=$AUTH_TOKEN + +description: | + This workload emulates CRUD operations for the Stargate JSON API. + It generates a simple JSON document to be used for writes and updates. + Note that jsonapi_port should reflect the port where the JSON API is exposed (defaults to 8080). + +scenarios: + default: + schema: run driver=http tags==block:schema threads==1 cycles==UNDEF + write: run driver=http tags==name:"write.*" cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + read: run driver=http tags==name:"read.*" cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + update: run driver=http tags==name:"update.*" cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + delete: run driver=http tags==name:"delete.*" cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + +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('<>') + # http request id + request_id: ToHashedUUID(); ToString(); + + seq_key: Mod(<>); ToString() -> String + random_key: Uniform(0,<>); ToString() -> String + + user_id: ToHashedUUID(); ToString() -> String + created_on: Uniform(1262304000,1577836800) -> long + gender: WeightedStrings('M:10;F:10;O:1') + full_name: FullNames() + married: ModuloToBoolean() + city: Cities() + country_code: CountryCodes() + lat: Uniform(-180d, 180d) + lng: Hash() -> long; Uniform(-180d, 180d) + friend_id: Add(-1); ToHashedUUID(); ToString() -> String + +blocks: + schema: + ops: + create-namespace: + method: POST + uri: <>://{weighted_hosts}:<><>/v1 + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createNamespace": { + "name": "<>" + } + } + + # TODO schema deletion not yet addressed by JSON API Spec + #delete-collection: + # method: POST + # uri: <>://{weighted_hosts}:<><>/v1/<> + # Accept: "application/json" + # X-Cassandra-Request-Id: "{request_id}" + # X-Cassandra-Token: "<>" + # ok-status: "[2-4][0-9][0-9]" + # body: | + # { + # "deleteCollection": { + # "name": "<>" + # } + # } + + create-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createCollection": { + "name": "<>" + } + } + + write: + ops: + # aka insertOne + write-document: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "insertOne" : { + "document" : { + "_id" : "{seq_key}", + "user_id": "{user_id}", + "created_on": {created_on}, + "gender": "{gender}", + "full_name": "{full_name}", + "married": {married}, + "address": { + "primary": { + "city": "{city}", + "cc": "{country_code}" + }, + "secondary": {} + }, + "coordinates": [ + {lat}, + {lng} + ], + "children": [], + "friends": [ + "{friend_id}" + ] + } + } + } + + read: + ops: + # aka findOne with _id as filter + read-document: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "findOne" : { + "filter" : { + "_id" : "{random_key}" + } + } + } + + update: + ops: + # aka findOneAndUpdate + # for parity with other tests this only uses set, not unset, no return value + update-document: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "findOneAndUpdate" : { + "filter": { + "_id" : "{random_key} + }, + "update": { + "$set": { + "user_id": "{user_id}", + "created_on": {created_on}, + "gender": "{gender}", + "full_name": "{full_name}", + "married": {married}, + "address": { + "primary": { + "city": "{city}", + "cc": "{country_code}" + }, + "secondary": {} + }, + "coordinates": [ + {lat}, + {lng} + ], + "children": [], + "friends": [ + "{friend_id}" + ], + "debt": null + } + } + } + } + + delete: + ops: + delete-document: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "findOne" : { + "filter" : { + "_id" : "{random_key}" + } + } + } diff --git a/nosqlbench/http-jsonapi-crud-dataset.md b/nosqlbench/http-jsonapi-crud-dataset.md new file mode 100644 index 0000000000..31d7610471 --- /dev/null +++ b/nosqlbench/http-jsonapi-crud-dataset.md @@ -0,0 +1,41 @@ +# Documents API CRUD using an external Dataset + +## Description + +The Documents API CRUD Dataset workflow targets Stargate's Documents API using JSON documents from an external dataset. +The [dataset](#dataset) is mandatory and should contain a JSON document per row that should be used as the input for write and update operations. +This workflow is perfect for testing Stargate performance using your own JSON dataset or any other realistic dataset. + +In contrast to other workflows, this one is not split into ramp-up and main phases. +Instead, there is only the main phase with 4 different load types (write, read, update and delete). + +## Named Scenarios + +### default + +The default scenario for http-jsonapi-crud-dataset.yaml runs each type of the main phase sequentially: write, read, update and delete. +This means that setting cycles for each of the phases should be done using the: `write-cycles`, `read-cycles`, `update-cycles` and `delete-cycles`. +The default value for all 4 cycles variables is the amount of documents to process (see [Workload Parameters](#workload-parameters)). + +Note that error handling is set to `errors=timer,warn`, which means that in case of HTTP errors the scenario is not stopped. + +## Dataset + +### JSON Documents + +As explained above, in order to run the workflow a file containing JSON documents is needed. +If you don't have a dataset at hand, please have a look at [awesome-json-datasets](https://github.com/jdorfman/awesome-json-datasets). +You can use exposed public APIs to create a realistic dataset of your choice. + +For example, you can easily create a dataset containing [Bitcoin unconfirmed transactions](https://gist.github.com/ivansenic/e280a89aba6420acb4f587d3779af774). + +```bash +curl 'https://blockchain.info/unconfirmed-transactions?format=json&limit=5000' | jq -c '.txs | .[]' > blockchain-unconfirmed-transactions.json +``` + +Above command creates a dataset with 5.000 latest unconfirmed transactions. + +## Workload Parameters + +- `docscount` - the number of documents to process in each step of a scenario (default: `10_000_000`) +- `dataset_file` - the file to read the JSON documents from (note that if number of documents in a file is smaller than the `docscount` parameter, the documents will be reused) diff --git a/nosqlbench/http-jsonapi-crud-dataset.yaml b/nosqlbench/http-jsonapi-crud-dataset.yaml new file mode 100644 index 0000000000..8b89256265 --- /dev/null +++ b/nosqlbench/http-jsonapi-crud-dataset.yaml @@ -0,0 +1,116 @@ +min_version: "4.17.15" + +description: | + This workload emulates CRUD operations for the Stargate Documents API. + It requires a data set file, where each line is a single JSON document to be used for writes and updates. + Note that jsonapi_port should reflect the port where the Docs API is exposed (defaults to 8080). + +scenarios: + default: + schema: run driver=http tags==block:schema threads==1 cycles==UNDEF + write: run driver=http tags==name:"write.*" cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + read: run driver=http tags==name:"read.*" cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + update: run driver=http tags==name:"update.*" cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + delete: run driver=http tags==name:"delete.*" cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10000000)) threads=auto errors=timer,warn + +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('<>') + # http request id + request_id: ToHashedUUID(); ToString(); + + seq_key: Mod(<>); ToString() -> String + random_key: Uniform(0,<>); ToString() -> String + +blocks: + # TODO schema creation not yet addressed by JSON API Spec + schema: + ops: + create-namespace: + method: POST + uri: <>://{weighted_hosts}:<><>/v1 + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createNamespace": { + "name": "<>" + } + } + + # TODO schema deletion not yet addressed by JSON API Spec + delete-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + ok-status: "[2-4][0-9][0-9]" + body: | + { + "deleteCollection": { + "name": "<>" + } + } + + create-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/namespaces/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createCollection": { + "name": "<>" + } + } + + main: + bindings: + document_json: ModuloLineToString('<>'); + ops: + # TODO expect the document have the ID in it? + write-document: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: "{document_json}" + + read-document: + method: GET + uri: <>://{weighted_hosts}:<><>/v2/namespaces/<>/collections/<>/{random_key} + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + ok-status: "[2-4][0-9][0-9]" + + update-document: + method: PUT + uri: <>://{weighted_hosts}:<><>/v2/namespaces/<>/collections/<>/{random_key} + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: "{document_json}" + + delete-document: + method: DELETE + uri: <>://{weighted_hosts}:<><>/v2/namespaces/<>/collections/<>/{seq_key} + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + ok-status: "[2-4][0-9][0-9]" diff --git a/nosqlbench/http-jsonapi-keyvalue.yaml b/nosqlbench/http-jsonapi-keyvalue.yaml new file mode 100644 index 0000000000..fb0ca35381 --- /dev/null +++ b/nosqlbench/http-jsonapi-keyvalue.yaml @@ -0,0 +1,136 @@ +min_version: "4.17.15" + +description: | + This workload emulates a key-value data model and access patterns. + This should be identical to the cql variant except for: + - Schema creation with the Docs API, we don't use cql because the Docs API is opinionated about schema. + - There is no instrumentation with the http driver. + - There is no async mode with the http driver. + Note that jsonapi_port should reflect the port where the Docs API is exposed (defaults to 8080). + +scenarios: + default: + schema: run driver=http tags==block:schema threads==1 cycles==UNDEF + rampup: run driver=http tags==block:rampup cycles===TEMPLATE(rampup-cycles,10000000) threads=auto + main: run driver=http tags==block:main cycles===TEMPLATE(main-cycles,10000000) 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('<>') + # http request id + request_id: ToHashedUUID(); ToString(); + + seq_key: Mod(<>); ToString() -> String + seq_value: Hash(); Mod(<>); ToString() -> String + rw_key: <>)->int>>; ToString() -> String + rw_value: Hash(); <>)->int>>; ToString() -> String + +blocks: + # TODO schema creation not yet addressed by JSON API Spec + schema: + ops: + create-namespace: + method: POST + uri: <>://{weighted_hosts}:<><>/v1 + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createNamespace": { + "name": "<>" + } + } + + # TODO schema deletion not yet addressed by JSON API Spec + delete-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + ok-status: "[2-4][0-9][0-9]" + body: | + { + "deleteCollection": { + "name": "<>" + } + } + + create-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/namespaces/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createCollection": { + "name": "<>" + } + } + + rampup: + ops: + rampup-insert: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "insertOne" : { + "document" : { + "_id" : "{seq_key}", + "{seq_key}" : "{seq_value}" + } + } + } + + main: + params: + ratio: <> + ops: + main-select: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + body: | + { + "findOne" : { + "filter" : { + "_id" : "{random_key}" + } + } + } + + main-write: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "findOneAndUpdate" : { + "filter": { + "_id" : "{rw_key}" + }, + "update": { + "$set": { + "{rw_key}":"{rw_value}" + } + } + } + } diff --git a/nosqlbench/http-jsonapi-search-advanced.md b/nosqlbench/http-jsonapi-search-advanced.md new file mode 100644 index 0000000000..5e60f1409b --- /dev/null +++ b/nosqlbench/http-jsonapi-search-advanced.md @@ -0,0 +1,65 @@ +# JSON API Search Advanced + +## Description + +The JSON API Search Advanced workflow targets Stargate's JSON API using generated JSON documents. Specifically, it looks to benchmark more advanced search cases, using both complex boolean logic and filters that aren't natively supported by the underlying data store. +By default, the documents used are sharing the same structure and are approximately half a kilobyte in size each: + +* Each document has 15 leaf values, with a maximum depth of 3 +* there is at least one `string`, `boolean`, `number` and `null` leaf +* there is one array with `double` values and one with `string` values +* there is one empty array and one empty map + +The example JSON looks like: + +```json +{ + "user_id":"56fd76f6-081d-401a-85eb-b1d9e5bba058", + "created_on":1476743286, + "full_name":"Andrew Daniels", + "married":true, + "address":{ + "primary":{ + "cc":"IO", + "city":"Okmulgee" + }, + "secondary":{ + + } + }, + "coordinates":[ + 64.65964627052323, + -122.35334535072856 + ], + "children":[ + + ], + "friends":[ + "3df498b1-9568-4584-96fd-76f6081da01a" + ], + "debt":null, + "match1": 0, // or 1000 + "match2": "true", // or "false" + "match3": true // or false +} +``` + +## Filters tested + +The advanced search workload can test the following `where` clauses: +- in: `match1 IN [0]` +- not-in: `match2 NOT IN ["false"]` +- mem-and: `match2 EQ "true" AND match3 NOT EQ false` +- mem-or: `match1 LT 1 OR match3 EXISTS` +- complex1: `match1 EQ 0 AND (match2 EQ "true" OR match3 EQ false)` +- complex2: `(match1 LTE 0 OR match2 EQ "false") AND (match2 EQ "false" OR match3 EQ true)` +- complex3: `(match1 LTE 0 AND match2 EQ "true") OR (match2 EQ "false" AND match3 EQ true)` + +## Workload Parameters + +- `docscount` - the number of documents to write during rampup (default: `10_000_000`) +- `docpadding` - the number of fields to add to each document; useful for writing larger documents. A value of e.g. `5` would make each document have 20 leaf values, instead of 15. (default: `0`) +- `match-ratio` - a value between 0 and 1 detailing what ratio of the documents written should match the search parameters. If match-ratio is e.g. `0.1` then approximately one-tenth of the documents will have `match1`, `match2`, and `match3` values that are `0`, `"true"`, and `true`, respectively. (default: `0.01`) +- `fields` - the URL-encoded value for `fields` that you would send to the Docs API. This restricts the fields returned during benchmarking. + + diff --git a/nosqlbench/http-jsonapi-search-advanced.yaml b/nosqlbench/http-jsonapi-search-advanced.yaml new file mode 100644 index 0000000000..dc9895bc8d --- /dev/null +++ b/nosqlbench/http-jsonapi-search-advanced.yaml @@ -0,0 +1,625 @@ +min_version: "4.17.31" + +description: | + This workload emulates advanced search filter combinations for the Stargate Documents API. + During the rampup phase, it generates documents, writes them to a table, and then warms up the search paths. + During the main phase it performs various basic search filters and times their execution. + Note that jsonapi_port should reflect the port where the Docs API is exposed (defaults to 8080). + +# These are the filter combinations tested in this workload, and their names: +# in: match1 IN [0] +# not-in: match2 NOT IN ["false"] +# mem-and: match2 EQ "true" AND match3 NOT EQ false +# mem-or: match1 LT 1 OR match3 EXISTS +# complex1: match1 EQ 0 AND (match2 EQ "true" OR match3 EQ false) +# complex2: (match1 LTE 0 OR match2 EQ "false") AND (match2 EQ "false" OR match3 EQ true) +# complex3: (match1 LTE 0 AND match2 EQ "true") OR (match2 EQ "false" AND match3 EQ true) +scenarios: + schema: run driver=http tags==phase:schema threads==<> cycles==UNDEF + rampup: + write: run driver=http tags==name:"rampup-put.*" cycles===TEMPLATE(docscount,10000000) docpadding=TEMPLATE(docpadding,0) match-ratio=TEMPLATE(match-ratio,0.01) threads=<> errors=timer,warn + read: run driver=http tags==phase:"rampup-get.*" cycles===TEMPLATE(rampup-cycles, 10000000) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + main: + all: run driver=http tags==block:main cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-in: run driver=http tags==name:main-get-in,filter:in cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-not-in: run driver=http tags==name:main-get-not-in cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-mem-and: run driver=http tags==name:main-get-mem-and cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-mem-or: run driver=http tags==name:main-get-mem-or cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-complex1: run driver=http tags==name:main-get-complex1 cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-complex2: run driver=http tags==name:main-get-complex2 cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-complex3: run driver=http tags==name:main-get-complex3 cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + +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('<>') + # http request id + request_id: ToHashedUUID(); ToString(); + + seq_key: Mod(<>); ToString() -> String + random_key: Uniform(0,<>); ToString() -> String + + user_id: ToHashedUUID(); ToString() -> String + created_on: Uniform(1262304000,1577836800) -> long + full_name: FullNames() + married: ModuloToBoolean() + city: Cities() + country_code: CountryCodes() + lat: Uniform(-180d, 180d) + lng: Hash() -> long; Uniform(-180d, 180d) + friend_id: Add(-1); ToHashedUUID(); ToString() -> String + + match1: Identity(); CoinFunc(<>, FixedValue(0), FixedValue(1000)) + match2: Identity(); CoinFunc(<>, FixedValue("true"), FixedValue("false")) + match3: Identity(); CoinFunc(<>, FixedValue("true"), FixedValue("false")) + + additional_fields: ListSizedStepped(<>,Template("\"{}\":{}",Identity(),Identity())); ToString(); ReplaceAll('\[\"', ',\"'); ReplaceAll('\[', ''); ReplaceAll('\]', '') -> String + +blocks: + schema: + statements: + create-namespace: + method: POST + uri: <>://{weighted_hosts}:<><>/v1 + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createNamespace": { + "name": "<>" + } + } + + # TODO schema deletion not yet addressed by JSON API Spec + #delete-collection: + # method: POST + # uri: <>://{weighted_hosts}:<><>/v1/<> + # Accept: "application/json" + # X-Cassandra-Request-Id: "{request_id}" + # X-Cassandra-Token: "<>" + # ok-status: "[2-4][0-9][0-9]" + # body: | + # { + # "deleteCollection": { + # "name": "<>" + # } + # } + + create-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createCollection": { + "name": "<>" + } + } + + rampup: + ops: + rampup-put: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "insertOne": { + "document": { + "_id": "{seq_key}", + "user_id": "{user_id}", + "created_on": {created_on}, + "full_name": "{full_name}", + "married": {married}, + "address": { + "primary": { + "city": "{city}", + "cc": "{country_code}" + }, + "secondary": {} + }, + "coordinates": [ + {lat}, + {lng} + ], + "children": [], + "friends": [ + "{friend_id}" + ], + "debt": null, + "match1": {match1}, + "match2": "{match2}", + "match3": {match3} + {additional_fields} + } + } + } + + # where={"match1":{"$in":[0]}} + rampup-get-in: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match1" : { + "in": [0] + } + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match2":{"$nin":["false"]}} + rampup-get-not-in: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match2" : { + "$nin": ["false"] + } + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match2":{"$eq":"true"},"match3":{"$ne": false}} + rampup-get-mem-and: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match2" : { + "$eq": "true" + }, + "match3" : { + "ne": false + }, + }, + "options": { + "pageSize": <> + } + } + } + + rampup-get-mem-or: + # where={"$or":[{"match1":{"$lt":1}},{"match3":{"$exists":true}}]} + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$or": [ + { + "match1": { + "$lt":1 + } + }, + { + "match3": { + "$exists": true + } + } + ] + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$and":[{"match1":{"$eq":0}},{"$or":[{"match2":{"$eq":"true"}},{"match3":{"$eq":false}}]}]} + rampup-get-complex1: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$and": [ + { + "match1": { + "$eq":0 + } + }, + { + "$or": [ + { + "match2": { + "$eq":"true" + } + }, + { + "match3": { + "$eq":false + } + } + ] + } + ] + }, + "options": { + "pageSize": <> + } + } + } + + rampup-get-complex2: + # where={"$and":[{"$or":[{"match1":{"$lte":0}},{"match2":{"$eq":"false"}}]},{"$or":[{"match2":{"$eq":"false"}},{"match3":{"$eq":true}}]}]} + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$and": [ + { + "$or": [ + { + "match1": { + "$lte":0 + } + }, + { + "match2": { + "$eq":"false" + } + } + ] + }, + { + "$or": [ + { + "match2": { + "$eq":"false" + } + }, + { + "match3": { + "$eq":true + } + } + ] + } + ] + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$or":[{"$and":[{"match1":{"$lte":0}},{"match2":{"$eq":"true"}}]},{"$and":[{"match2":{"$eq":"false"}},{"match3":{"$eq":true}}]}]} + rampup-get-complex3: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$or": [ + { + "$and":[ + { + "match1": { + "$lte": 0 + } + }, + { + "match2": { + "$eq": "true" + } + } + ] + }, + { + "$and": [ + { + "match2": { + "$eq":"false" + } + }, + { + "match3": { + "$eq":true + } + } + ] + } + ] + }, + "options": { + "pageSize": <> + } + } + } + + main: + ops: + # where={"match1":{"$in":[0]}} + main-get-in: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match1" : { + "$in": [0] + } + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match2":{"$nin":["false"]}} + main-get-not-in: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match2" : { + "$nin": ["false"] + } + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match2":{"$eq":"true"},"match3":{"$ne": false}} + main-get-mem-and: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match2": { + "$eq": "true" + }, + "match3": { + "$ne": false + } + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$or":[{"match1":{"$lt":1}},{"match3":{"$exists":true}}]} + main-get-mem-or: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$or": [ + { + "match1": { + "$lt":1 + } + }, + { + "match3": { + "$exists": true + } + } + ] + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$and":[{"match1":{"$eq":0}},{"$or":[{"match2":{"$eq":"true"}},{"match3":{"$eq":false}}]}]} + main-get-complex1: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$and": [ + { + "match1": { + "$eq":0 + } + }, + { + "$or": [ + { + "match2": { + "$eq":"true" + } + }, + { + "match3": { + "$eq":false + } + } + ] + } + ] + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$and":[{"$or":[{"match1":{"$lte":0}},{"match2":{"$eq":"false"}}]},{"$or":[{"match2":{"$eq":"false"}},{"match3":{"$eq":true}}]}]} + main-get-complex2: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$and": [ + { + "$or": [ + { + "match1": { + "$lte":0 + } + }, + { + "match2": { + "$eq":"false" + } + } + ] + }, + { + "$or": [ + { + "match2": { + "$eq": "false" + } + }, + { + "match3": { + "$eq":true + } + } + ] + } + ] + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$or":[{"$and":[{"match1":{"$lte":0}},{"match2":{"$eq":"true"}}]},{"$and":[{"match2":{"$eq":"false"}},{"match3":{"$eq":true}}]}]} + main-get-complex3: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "$or": [ + { + "$and": [ + { + "match1": { + "$lte":0 + } + }, + { + "match2": { + "$eq":"true" + } + } + ] + }, + { + "$and": [ + { + "match2": { + "$eq":"false" + } + }, + { + "match3": { + "$eq": true + } + } + ] + } + ] + }, + "options": { + "pageSize": <> + } + } + } diff --git a/nosqlbench/http-jsonapi-search-basic.md b/nosqlbench/http-jsonapi-search-basic.md new file mode 100644 index 0000000000..61f9d22df9 --- /dev/null +++ b/nosqlbench/http-jsonapi-search-basic.md @@ -0,0 +1,63 @@ +# JSON API Search Basic + +## Description + +The JSON API Search Basic workflow targets Stargate's JSON API using generated JSON documents. Specifically, it looks to benchmark basic search cases, using the filters that are supported by the underlying data store. +By default, the documents used are sharing the same structure and are approximately half a kilobyte in size each: + +* Each document has 15 leaf values, with a maximum depth of 3 +* there is at least one `string`, `boolean`, `number` and `null` leaf +* there is one array with `double` values and one with `string` values +* there is one empty array and one empty map + +The example JSON looks like: + +```json +{ + "user_id":"56fd76f6-081d-401a-85eb-b1d9e5bba058", + "created_on":1476743286, + "full_name":"Andrew Daniels", + "married":true, + "address":{ + "primary":{ + "cc":"IO", + "city":"Okmulgee" + }, + "secondary":{ + + } + }, + "coordinates":[ + 64.65964627052323, + -122.35334535072856 + ], + "children":[ + + ], + "friends":[ + "3df498b1-9568-4584-96fd-76f6081da01a" + ], + "debt":null, + "match1": 0, // or 1000 + "match2": "true", // or "false" + "match3": true // or false +} +``` + +## Filters tested + +The basic search workload can test the following `where` clauses: +- eq: `match3 EQ true` +- lt: `match1 LT 1` +- and: `match1 LT 1 AND match2 EQ "true"` +- or: `match1 LT 1 OR match2 EQ "true" or match3 EQ true` +- or-single-match: `match1 LT 1 OR match2 EQ "notamatch"` + +## Workload Parameters + +- `docscount` - the number of documents to write during rampup (default: `10_000_000`) +- `docpadding` - the number of fields to add to each document; useful for writing larger documents. A value of e.g. `5` would make each document have 20 leaf values, instead of 15. (default: `0`) +- `match-ratio` - a value between 0 and 1 detailing what ratio of the documents written should match the search parameters. If match-ratio is e.g. `0.1` then approximately one-tenth of the documents will have `match1`, `match2`, and `match3` values that are `0`, `"true"`, and `true`, respectively. (default: `0.01`) +- `fields` - the URL-encoded value for `fields` that you would send to the Docs API. This restricts the fields returned during benchmarking. + + diff --git a/nosqlbench/http-jsonapi-search-basic.yaml b/nosqlbench/http-jsonapi-search-basic.yaml new file mode 100644 index 0000000000..18fd8ccc9a --- /dev/null +++ b/nosqlbench/http-jsonapi-search-basic.yaml @@ -0,0 +1,353 @@ +min_version: "4.17.31" + +description: | + This workload emulates basic search operations for the Stargate Documents API. + During the rampup phase, it generates documents, writes them to a table, and then warms up the search paths. + During the main phase it performs various basic search filters and times their execution. + Note that jsonapi_port should reflect the port where the Docs API is exposed (defaults to 8080). + +scenarios: + # TODO schema creation not yet addressed by JSON API Spec + schema: run driver=http tags==block:schema threads==<> cycles==UNDEF + rampup: + write: run driver=http tags==name:"rampup-put.*" cycles===TEMPLATE(docscount,10000000) docpadding=TEMPLATE(docpadding,0) match-ratio=TEMPLATE(match-ratio,0.01) threads=<> errors=timer,warn + read: run driver=http tags==name:"rampup-get.*" cycles===TEMPLATE(rampup-cycles, 10000000) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + main: + all: run driver=http tags==block:main cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-eq: run driver=http tags==name:main-get-eq,filter:eq cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-lt: run driver=http tags==name:main-get-lt cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-and: run driver=http tags==name:main-get-and cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-or: run driver=http tags==name:main-get-or cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + get-or-single-match: run driver=http tags==name:main-get-or-single-match cycles===TEMPLATE(read-cycles,TEMPLATE(docscount,10000000)) page-size=TEMPLATE(page-size,3) fields=TEMPLATE(fields,%5b%5d) threads=<> errors=timer,warn + +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('<>') + # http request id + request_id: ToHashedUUID(); ToString(); + + seq_key: Mod(<>); ToString() -> String + random_key: Uniform(0,<>); ToString() -> String + + user_id: ToHashedUUID(); ToString() -> String + created_on: Uniform(1262304000,1577836800) -> long + full_name: FullNames() + married: ModuloToBoolean() + city: Cities() + country_code: CountryCodes() + lat: Uniform(-180d, 180d) + lng: Hash() -> long; Uniform(-180d, 180d) + friend_id: Add(-1); ToHashedUUID(); ToString() -> String + + match1: Identity(); CoinFunc(<>, FixedValue(0), FixedValue(1000)) + match2: Identity(); CoinFunc(<>, FixedValue("true"), FixedValue("false")) + additional_fields: ListSizedStepped(<>,Template("\"{}\":{}",Identity(),Identity())); ToString(); ReplaceAll('\[\"', ',\"'); ReplaceAll('\[', ''); ReplaceAll('\]', '') -> String + +blocks: + # TODO schema creation not yet addressed by JSON API Spec + schema: + ops: + create-namespace: + method: POST + uri: <>://{weighted_hosts}:<><>/v1 + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createNamespace": { + "name": "<>" + } + } + + # TODO schema deletion not yet addressed by JSON API Spec + #delete-collection: + # method: POST + # uri: <>://{weighted_hosts}:<><>/v1/<> + # Accept: "application/json" + # X-Cassandra-Request-Id: "{request_id}" + # X-Cassandra-Token: "<>" + # ok-status: "[2-4][0-9][0-9]" + # body: | + # { + # "deleteCollection": { + # "name": "<>" + # } + # } + + create-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "createCollection": { + "name": "<>" + } + } + + rampup: + ops: + rampup-put: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "insertOne": { + "document": { + "_id": "{seq_key}", + "user_id": "{user_id}", + "created_on": { created_on }, + "full_name": "{full_name}", + "married": { married }, + "address": { + "primary": { + "city": "{city}", + "cc": "{country_code}" + }, + "secondary": { } + }, + "coordinates": [ + { lat }, + { lng } + ], + "children": [ ], + "friends": [ + "{friend_id}" + ], + "debt": null, + "match1": { match1 }, + "match2": "{match2}", + "match3": { match2 } + { additional_fields } + } + } + } + + # where={"match3":{"$eq":true}} + rampup-get-eq: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match3" : {"$eq":true} + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match1":{"$lt":1}} + rampup-get-lt: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match1" : {"$lt":1} + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match1":{"$lt":1},"match2":{"$eq":"true"}} + rampup-get-and: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match1" : {"$lt":1}, + "match2" : {"$eq":"true"} + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$or":[{"match1":{"$lt":1}},{"match3":{"$eq":true}}]} + rampup-get-or: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "or" : [ + {"match1" : {"$lt":1}}, + {"match3" : {"$eq":true}} + ] + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$or":[{"match1":{"$lt":1}},{"match2":{"$eq":"notamatch"}}]} + main-get-or-single-match: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "or" : [ + {"match1" : {"$lt":1}}, + {"match2" : {"$eq":"notamatch"}} + ] + }, + "options": { + "pageSize": <> + } + } + } + + main: + ops: + # where={"match3":{"$eq":true}} + main-get-eq: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match3" : {"$eq":true} + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match1":{"$lt":1}} + main-get-lt: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match1" : {"$lt":1} + }, + "options": { + "pageSize": <> + } + } + } + + # where={"match1":{"$lt":1},"match2":{"$eq":"true"}} + main-get-and: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "match1" : {"$lt":1}, + "match2" : {"$eq":"true"} + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$or":[{"match1":{"$lt":1}},{"match3":{"$eq":true}}]} + main-get-or: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "or" : [ + {"match1" : {"$lt":1}}, + {"match3" : {"$eq":true}} + ] + }, + "options": { + "pageSize": <> + } + } + } + + # where={"$or":[{"match1":{"$lt":1}},{"match2":{"$eq":"notamatch"}}]} + main-get-or-single-match: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<>/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "find" : { + "filter" : { + "or" : [ + {"match1" : {"$lt":1}}, + {"match2" : {"$eq":"notamatch"}} + ] + }, + "options": { + "pageSize": <> + } + } + } From 23efab43d7eb0864f19e05337965a56b3b081cd9 Mon Sep 17 00:00:00 2001 From: Jeffrey Carpenter Date: Wed, 15 Feb 2023 14:01:18 -0700 Subject: [PATCH 2/3] review feedback --- nosqlbench/http-jsonapi-keyvalue.yaml | 37 ++++++++++---------- nosqlbench/http-jsonapi-search-advanced.yaml | 28 +++++++-------- nosqlbench/http-jsonapi-search-basic.yaml | 22 ++++++------ 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/nosqlbench/http-jsonapi-keyvalue.yaml b/nosqlbench/http-jsonapi-keyvalue.yaml index fb0ca35381..2d65c585ea 100644 --- a/nosqlbench/http-jsonapi-keyvalue.yaml +++ b/nosqlbench/http-jsonapi-keyvalue.yaml @@ -30,7 +30,6 @@ bindings: rw_value: Hash(); <>)->int>>; ToString() -> String blocks: - # TODO schema creation not yet addressed by JSON API Spec schema: ops: create-namespace: @@ -43,28 +42,28 @@ blocks: body: | { "createNamespace": { - "name": "<>" + "name": "<>" } } # TODO schema deletion not yet addressed by JSON API Spec - delete-collection: - method: POST - uri: <>://{weighted_hosts}:<><>/v1/<> - Accept: "application/json" - X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "<>" - ok-status: "[2-4][0-9][0-9]" - body: | - { - "deleteCollection": { - "name": "<>" - } - } + #delete-collection: + # method: POST + # uri: <>://{weighted_hosts}:<><>/v1/<> + # Accept: "application/json" + # X-Cassandra-Request-Id: "{request_id}" + # X-Cassandra-Token: "<>" + # ok-status: "[2-4][0-9][0-9]" + # body: | + # { + # "deleteCollection": { + # "name": "<>" + # } + # } create-collection: method: POST - uri: <>://{weighted_hosts}:<><>/v1/namespaces/<> + uri: <>://{weighted_hosts}:<><>/v1/namespaces/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" X-Cassandra-Token: "<>" @@ -80,7 +79,7 @@ blocks: ops: rampup-insert: method: POST - uri: <>://{weighted_hosts}:<><>/v1/<>/<> + uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" X-Cassandra-Token: "<>" @@ -101,7 +100,7 @@ blocks: ops: main-select: method: POST - uri: <>://{weighted_hosts}:<><>/v1/<>/<> + uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" X-Cassandra-Token: "<>" @@ -116,7 +115,7 @@ blocks: main-write: method: POST - uri: <>://{weighted_hosts}:<><>/v1/<>/<> + uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" X-Cassandra-Token: "<>" diff --git a/nosqlbench/http-jsonapi-search-advanced.yaml b/nosqlbench/http-jsonapi-search-advanced.yaml index dc9895bc8d..efb1577a1f 100644 --- a/nosqlbench/http-jsonapi-search-advanced.yaml +++ b/nosqlbench/http-jsonapi-search-advanced.yaml @@ -163,7 +163,7 @@ blocks: } }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -185,7 +185,7 @@ blocks: } }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -210,7 +210,7 @@ blocks: }, }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -241,7 +241,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -281,7 +281,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -330,7 +330,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -379,7 +379,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -403,7 +403,7 @@ blocks: } }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -425,7 +425,7 @@ blocks: } }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -450,7 +450,7 @@ blocks: } }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -481,7 +481,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -521,7 +521,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -570,7 +570,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -619,7 +619,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } diff --git a/nosqlbench/http-jsonapi-search-basic.yaml b/nosqlbench/http-jsonapi-search-basic.yaml index 18fd8ccc9a..7fb331ae36 100644 --- a/nosqlbench/http-jsonapi-search-basic.yaml +++ b/nosqlbench/http-jsonapi-search-basic.yaml @@ -7,7 +7,6 @@ description: | Note that jsonapi_port should reflect the port where the Docs API is exposed (defaults to 8080). scenarios: - # TODO schema creation not yet addressed by JSON API Spec schema: run driver=http tags==block:schema threads==<> cycles==UNDEF rampup: write: run driver=http tags==name:"rampup-put.*" cycles===TEMPLATE(docscount,10000000) docpadding=TEMPLATE(docpadding,0) match-ratio=TEMPLATE(match-ratio,0.01) threads=<> errors=timer,warn @@ -48,7 +47,6 @@ bindings: additional_fields: ListSizedStepped(<>,Template("\"{}\":{}",Identity(),Identity())); ToString(); ReplaceAll('\[\"', ',\"'); ReplaceAll('\[', ''); ReplaceAll('\]', '') -> String blocks: - # TODO schema creation not yet addressed by JSON API Spec schema: ops: create-namespace: @@ -151,7 +149,7 @@ blocks: "match3" : {"$eq":true} }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -171,7 +169,7 @@ blocks: "match1" : {"$lt":1} }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -192,7 +190,7 @@ blocks: "match2" : {"$eq":"true"} }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -215,7 +213,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -238,7 +236,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -260,7 +258,7 @@ blocks: "match3" : {"$eq":true} }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -280,7 +278,7 @@ blocks: "match1" : {"$lt":1} }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -301,7 +299,7 @@ blocks: "match2" : {"$eq":"true"} }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -324,7 +322,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } @@ -347,7 +345,7 @@ blocks: ] }, "options": { - "pageSize": <> + "pageSize": <> } } } From e485fbf3913450b5e7fa9ed906580e9abfb645f0 Mon Sep 17 00:00:00 2001 From: Jeffrey Carpenter Date: Fri, 17 Feb 2023 16:03:21 -0700 Subject: [PATCH 3/3] delete collection now supported --- nosqlbench/http-jsonapi-crud-basic.yaml | 27 ++++++++++---------- nosqlbench/http-jsonapi-crud-dataset.yaml | 2 -- nosqlbench/http-jsonapi-keyvalue.yaml | 27 ++++++++++---------- nosqlbench/http-jsonapi-search-advanced.yaml | 27 ++++++++++---------- nosqlbench/http-jsonapi-search-basic.yaml | 27 ++++++++++---------- 5 files changed, 52 insertions(+), 58 deletions(-) diff --git a/nosqlbench/http-jsonapi-crud-basic.yaml b/nosqlbench/http-jsonapi-crud-basic.yaml index bd2da2ec8a..3476445a79 100644 --- a/nosqlbench/http-jsonapi-crud-basic.yaml +++ b/nosqlbench/http-jsonapi-crud-basic.yaml @@ -56,20 +56,19 @@ blocks: } } - # TODO schema deletion not yet addressed by JSON API Spec - #delete-collection: - # method: POST - # uri: <>://{weighted_hosts}:<><>/v1/<> - # Accept: "application/json" - # X-Cassandra-Request-Id: "{request_id}" - # X-Cassandra-Token: "<>" - # ok-status: "[2-4][0-9][0-9]" - # body: | - # { - # "deleteCollection": { - # "name": "<>" - # } - # } + delete-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "deleteCollection": { + "name": "<>" + } + } create-collection: method: POST diff --git a/nosqlbench/http-jsonapi-crud-dataset.yaml b/nosqlbench/http-jsonapi-crud-dataset.yaml index 8b89256265..16c8da2da9 100644 --- a/nosqlbench/http-jsonapi-crud-dataset.yaml +++ b/nosqlbench/http-jsonapi-crud-dataset.yaml @@ -44,7 +44,6 @@ blocks: } } - # TODO schema deletion not yet addressed by JSON API Spec delete-collection: method: POST uri: <>://{weighted_hosts}:<><>/v1/<> @@ -52,7 +51,6 @@ blocks: X-Cassandra-Request-Id: "{request_id}" X-Cassandra-Token: "<>" Content-Type: "application/json" - ok-status: "[2-4][0-9][0-9]" body: | { "deleteCollection": { diff --git a/nosqlbench/http-jsonapi-keyvalue.yaml b/nosqlbench/http-jsonapi-keyvalue.yaml index 2d65c585ea..92f90e0bdf 100644 --- a/nosqlbench/http-jsonapi-keyvalue.yaml +++ b/nosqlbench/http-jsonapi-keyvalue.yaml @@ -46,20 +46,19 @@ blocks: } } - # TODO schema deletion not yet addressed by JSON API Spec - #delete-collection: - # method: POST - # uri: <>://{weighted_hosts}:<><>/v1/<> - # Accept: "application/json" - # X-Cassandra-Request-Id: "{request_id}" - # X-Cassandra-Token: "<>" - # ok-status: "[2-4][0-9][0-9]" - # body: | - # { - # "deleteCollection": { - # "name": "<>" - # } - # } + delete-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "deleteCollection": { + "name": "<>" + } + } create-collection: method: POST diff --git a/nosqlbench/http-jsonapi-search-advanced.yaml b/nosqlbench/http-jsonapi-search-advanced.yaml index efb1577a1f..92447a7523 100644 --- a/nosqlbench/http-jsonapi-search-advanced.yaml +++ b/nosqlbench/http-jsonapi-search-advanced.yaml @@ -75,20 +75,19 @@ blocks: } } - # TODO schema deletion not yet addressed by JSON API Spec - #delete-collection: - # method: POST - # uri: <>://{weighted_hosts}:<><>/v1/<> - # Accept: "application/json" - # X-Cassandra-Request-Id: "{request_id}" - # X-Cassandra-Token: "<>" - # ok-status: "[2-4][0-9][0-9]" - # body: | - # { - # "deleteCollection": { - # "name": "<>" - # } - # } + delete-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "deleteCollection": { + "name": "<>" + } + } create-collection: method: POST diff --git a/nosqlbench/http-jsonapi-search-basic.yaml b/nosqlbench/http-jsonapi-search-basic.yaml index 7fb331ae36..7f3dd5bd89 100644 --- a/nosqlbench/http-jsonapi-search-basic.yaml +++ b/nosqlbench/http-jsonapi-search-basic.yaml @@ -63,20 +63,19 @@ blocks: } } - # TODO schema deletion not yet addressed by JSON API Spec - #delete-collection: - # method: POST - # uri: <>://{weighted_hosts}:<><>/v1/<> - # Accept: "application/json" - # X-Cassandra-Request-Id: "{request_id}" - # X-Cassandra-Token: "<>" - # ok-status: "[2-4][0-9][0-9]" - # body: | - # { - # "deleteCollection": { - # "name": "<>" - # } - # } + delete-collection: + method: POST + uri: <>://{weighted_hosts}:<><>/v1/<> + Accept: "application/json" + X-Cassandra-Request-Id: "{request_id}" + X-Cassandra-Token: "<>" + Content-Type: "application/json" + body: | + { + "deleteCollection": { + "name": "<>" + } + } create-collection: method: POST