From 0f0ef8a33f58fce6e66f345d331c6a6000e45139 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Fri, 14 Feb 2014 10:30:05 +0100 Subject: [PATCH] updated index docs --- Documentation/DbaManual/HandlingIndexes.md | 4 + Documentation/DbaManual/HandlingIndexesTOC.md | 1 + UnitTests/Makefile.unittests | 2 +- arangod/V8Server/v8-vocbase.cpp | 145 ++++++++- js/actions/api-index.js | 298 +++--------------- .../modules/org/arangodb/arango-collection.js | 178 +++++------ .../modules/org/arangodb/arango-collection.js | 178 +++++------ .../tests/shell-index-ensure.js | 0 .../modules/org/arangodb/arango-collection.js | 82 +---- 9 files changed, 367 insertions(+), 521 deletions(-) rename js/{server => common}/tests/shell-index-ensure.js (100%) diff --git a/Documentation/DbaManual/HandlingIndexes.md b/Documentation/DbaManual/HandlingIndexes.md index 39e5646640..a9c85ae114 100644 --- a/Documentation/DbaManual/HandlingIndexes.md +++ b/Documentation/DbaManual/HandlingIndexes.md @@ -130,6 +130,10 @@ Collection Methods {#HandlingIndexesCollectionMethods} @anchor HandlingIndexesDelete @copydetails JS_DropIndexVocbaseCol +@CLEARPAGE +@anchor HandlingIndexesEnsure +@copydetails JS_EnsureIndexVocbaseCol + @CLEARPAGE Database Methods {#HandlingIndexesDatabaseMethods} -------------------------------------------------- diff --git a/Documentation/DbaManual/HandlingIndexesTOC.md b/Documentation/DbaManual/HandlingIndexesTOC.md index 0966b8c859..641097ef01 100644 --- a/Documentation/DbaManual/HandlingIndexesTOC.md +++ b/Documentation/DbaManual/HandlingIndexesTOC.md @@ -10,6 +10,7 @@ TOC {#HandlingIndexesTOC} - @ref HandlingIndexesRead "collection.index" - @ref HandlingIndexesReadAll "collection.getIndexes" - @ref HandlingIndexesDelete "collection.dropIndex" + - @ref HandlingIndexesEnsure "collection.ensureIndex" - @ref HandlingIndexesDatabaseMethods - @ref HandlingIndexesDbRead "db._index" - @ref HandlingIndexesDbDelete "db._dropIndex" diff --git a/UnitTests/Makefile.unittests b/UnitTests/Makefile.unittests index 0c9bc9f1aa..db0d56901c 100755 --- a/UnitTests/Makefile.unittests +++ b/UnitTests/Makefile.unittests @@ -367,6 +367,7 @@ SHELL_COMMON = \ @top_srcdir@/js/common/tests/shell-graph-algorithms.js \ @top_srcdir@/js/common/tests/shell-graph-measurement.js \ @top_srcdir@/js/common/tests/shell-keygen.js \ + @top_srcdir@/js/common/tests/shell-index-ensure.js \ @top_srcdir@/js/common/tests/shell-simple-query.js \ @top_srcdir@/js/common/tests/shell-statement.js \ @top_srcdir@/js/common/tests/shell-transactions.js \ @@ -399,7 +400,6 @@ SHELL_SERVER_ONLY = \ @top_srcdir@/js/server/tests/shell-foxx-template-middleware.js \ @top_srcdir@/js/server/tests/shell-foxx-format-middleware.js \ @top_srcdir@/js/server/tests/shell-foxx-preprocessor.js \ - @top_srcdir@/js/server/tests/shell-index-ensure.js \ @top_srcdir@/js/server/tests/shell-skiplist-index.js \ @top_srcdir@/js/server/tests/shell-skiplist-rm-performance.js \ @top_srcdir@/js/server/tests/shell-skiplist-correctness.js diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 7c3944ede9..0ffe74b229 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -1121,6 +1121,7 @@ static int EnhanceIndexJson (v8::Arguments const& argv, // extract index type TRI_idx_type_e type = TRI_IDX_TYPE_UNKNOWN; + if (obj->Has(TRI_V8_SYMBOL("type")) && obj->Get(TRI_V8_SYMBOL("type"))->IsString()) { TRI_Utf8ValueNFC typeString(TRI_UNKNOWN_MEM_ZONE, obj->Get(TRI_V8_SYMBOL("type"))); @@ -1128,7 +1129,20 @@ static int EnhanceIndexJson (v8::Arguments const& argv, return TRI_ERROR_OUT_OF_MEMORY; } - type = TRI_TypeIndex(*typeString); + string t(*typeString); + // rewrite type "geo" into either "geo1" or "geo2", depending on the number of fields + if (t == "geo") { + t = "geo1"; + + if (obj->Has(TRI_V8_SYMBOL("fields")) && obj->Get(TRI_V8_SYMBOL("fields"))->IsArray()) { + v8::Handle f = v8::Handle::Cast(obj->Get(TRI_V8_SYMBOL("fields"))); + if (f->Length() == 2) { + t = "geo2"; + } + } + } + + type = TRI_TypeIndex(t.c_str()); } if (type == TRI_IDX_TYPE_UNKNOWN) { @@ -5706,7 +5720,6 @@ static v8::Handle JS_DatafileScanVocbaseCol (v8::Arguments const& arg /// @{ //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief ensures that an index exists /// @@ -5715,8 +5728,8 @@ static v8::Handle JS_DatafileScanVocbaseCol (v8::Arguments const& arg /// Ensures that an index according to the @FA{index-description} exists. A /// new index will be created if none exists with the given description. /// -/// The @FA{index-description} must contain at a `type` attribute. `type` can -/// be one of the following values: +/// The @FA{index-description} must contain at least a `type` attribute. +/// `type` can be one of the following values: /// - `hash`: hash index /// - `skiplist`: skiplist index /// - `fulltext`: fulltext index @@ -5725,9 +5738,121 @@ static v8::Handle JS_DatafileScanVocbaseCol (v8::Arguments const& arg /// - `geo2`: geo index, with two attributes /// - `cap`: cap constraint /// +/// Other attributes may be necessary, depending on the index type. +/// /// Calling this method returns an index object. Whether or not the index -/// object existed before the call or was created due to the call is indicated -/// in the return attribute `isNewlyCreated`. +/// object existed before the call is indicated in the return attribute +/// `isNewlyCreated`. +/// +/// @EXAMPLES +/// +/// Ensures that a unique hash index on attribute `name` exists: +/// +/// @EXAMPLE_ARANGOSH_RUN{EnsureIndexUniqueHash} +/// var cn = "products"; +/// db._drop(cn); +/// db._create(cn); +/// +/// var url = "/_api/index?collection=" + cn; +/// var body = { +/// type: "hash", +/// fields: [ "name" ], +/// unique: true +/// }; +/// +/// var response = logCurlRequest('POST', url, JSON.stringify(body)); +/// +/// assert(response.code === 201); +/// +/// logJsonResponse(response); +/// @END_EXAMPLE_ARANGOSH_RUN +/// +/// Re-ensures that a unique hash index on attribute `name` exists (the index +/// already exists): +/// +/// @EXAMPLE_ARANGOSH_RUN{EnsureIndexUniqueHashConfirm} +/// var cn = "products"; +/// db._drop(cn); +/// db._create(cn); +/// db.products.ensureIndex({ type: "hash", fields: [ "name" ], unique: true }); +/// +/// var url = "/_api/index?collection=" + cn; +/// var body = { +/// type: "hash", +/// fields: [ "name" ], +/// unique: true +/// }; +/// +/// var response = logCurlRequest('POST', url, JSON.stringify(body)); +/// +/// assert(response.code === 200); +/// +/// logJsonResponse(response); +/// @END_EXAMPLE_ARANGOSH_RUN +/// +/// +/// Ensures that a skiplist index on attributes `category1` and `category2` exists: +/// +/// @EXAMPLE_ARANGOSH_RUN{EnsureIndexSkiplist} +/// var cn = "products"; +/// db._drop(cn); +/// db._create(cn); +/// +/// var url = "/_api/index?collection=" + cn; +/// var body = { +/// type: "skiplist", +/// fields: [ "category1", "category2" ], +/// unique: false +/// }; +/// +/// var response = logCurlRequest('POST', url, JSON.stringify(body)); +/// +/// assert(response.code === 201); +/// +/// logJsonResponse(response); +/// @END_EXAMPLE_ARANGOSH_RUN +/// +/// Ensures that a cap constraint exists +/// +/// @EXAMPLE_ARANGOSH_RUN{EnsureIndexCap} +/// var cn = "logs"; +/// db._drop(cn); +/// db._create(cn); +/// +/// var url = "/_api/index?collection=" + cn; +/// var body = { +/// type: "cap", +/// size: 1000, +/// byteSize: 1048576 +/// }; +/// +/// var response = logCurlRequest('POST', url, JSON.stringify(body)); +/// +/// assert(response.code === 201); +/// +/// logJsonResponse(response); +/// @END_EXAMPLE_ARANGOSH_RUN +/// +/// Ensures that a geo index exists +/// +/// @EXAMPLE_ARANGOSH_RUN{EnsureIndexSkiplist} +/// var cn = "locations"; +/// db._drop(cn); +/// db._create(cn); +/// +/// var url = "/_api/index?collection=" + cn; +/// var body = { +/// type: "geo", +/// fields: [ "lat", "lon" ], +/// unique: false +/// }; +/// +/// var response = logCurlRequest('POST', url, JSON.stringify(body)); +/// +/// assert(response.code === 201); +/// +/// logJsonResponse(response); +/// @END_EXAMPLE_ARANGOSH_RUN /// //////////////////////////////////////////////////////////////////////////////// @@ -6832,9 +6957,9 @@ static v8::Handle JS_PropertiesVocbaseCol (v8::Arguments const& argv) /// /// @code /// arango> a1 = db.example.save({ a : 1 }); -/// { "_id" : "116308/3449537", "_rev" : "3449537" } +/// { "_id" : "example/3449537", "_key" : "3449537", "_rev" : "3449537" } /// arango> db.example.document(a1); -/// { "_id" : "116308/3449537", "_rev" : "3449537", "a" : 1 } +/// { "_id" : "example/3449537", "_key" : "3449537", "_rev" : "3449537", "a" : 1 } /// arango> db.example.remove(a1); /// true /// arango> db.example.document(a1); @@ -6847,9 +6972,9 @@ static v8::Handle JS_PropertiesVocbaseCol (v8::Arguments const& argv) /// /// @code /// arango> a1 = db.example.save({ a : 1 }); -/// { "_id" : "116308/3857139", "_rev" : "3857139" } +/// { "_id" : "example/3857139", "_key" : "3857139", "_rev" : "3857139" } /// arango> a2 = db.example.replace(a1, { a : 2 }); -/// { "_id" : "116308/3857139", "_rev" : "3922675", "_oldRev" : 3857139 } +/// { "_id" : "example/3857139", "_key" : "3857139", "_rev" : "3922675", "_oldRev" : 3857139 } /// arango> db.example.remove(a1); /// JavaScript exception in file '(arango)' at 1,18: [ArangoError 1200: conflict: cannot remove document] /// !db.example.remove(a1); diff --git a/js/actions/api-index.js b/js/actions/api-index.js index 069faa3f5c..01555a0c53 100644 --- a/js/actions/api-index.js +++ b/js/actions/api-index.js @@ -193,6 +193,7 @@ function get_api_index (req, res) { } //////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_post_api_index_cap /// @brief creates a cap constraint /// /// @RESTHEADER{POST /_api/index,creates a cap constraint} @@ -260,41 +261,8 @@ function get_api_index (req, res) { /// @END_EXAMPLE_ARANGOSH_RUN //////////////////////////////////////////////////////////////////////////////// -function post_api_index_cap (req, res, collection, body) { - if (body.hasOwnProperty("size") && - (typeof body.size !== "number" || body.size < 0)) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "expecting a valid size"); - return; - } - - if (body.hasOwnProperty("byteSize") && - (typeof body.byteSize !== "number" || body.byteSize < 0)) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "expecting a valid byteSize"); - return; - } - - var size = body.size || 0; - var byteSize = body.byteSize || 0; - - if (size <= 0 && byteSize <= 0) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "expecting a valid size and/or byteSize"); - return; - } - - var index = collection.ensureCapConstraint(size, byteSize); - - if (index.isNewlyCreated) { - actions.resultOk(req, res, actions.HTTP_CREATED, index); - } - else { - actions.resultOk(req, res, actions.HTTP_OK, index); - } -} - //////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_post_api_index_geo /// @brief creates a geo index /// /// @RESTHEADER{POST /_api/index,creates a geo-spatial index} @@ -393,94 +361,8 @@ function post_api_index_cap (req, res, collection, body) { /// @END_EXAMPLE_ARANGOSH_RUN //////////////////////////////////////////////////////////////////////////////// -function post_api_index_geo (req, res, collection, body) { - var fields = body.fields; - - if (! (fields instanceof Array)) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "fields must be a list of attribute paths: " + fields); - return; - } - - var index; - var constraint; - - if (body.hasOwnProperty("unique")) { - // try "unique" first - constraint = body.unique; - } - else if (body.hasOwnProperty("constraint")) { - // "constraint" next - constraint = body.constraint; - } - else { - constraint = false; - } - - if (fields.length === 1) { - - // attribute list and geoJson - if (body.hasOwnProperty("geoJson")) { - if (constraint) { - if (body.hasOwnProperty("ignoreNull")) { - index = collection.ensureGeoConstraint(fields[0], body.geoJson, body.ignoreNull); - } - else { - index = collection.ensureGeoConstraint(fields[0], body.geoJson, false); - } - } - else { - index = collection.ensureGeoIndex(fields[0], body.geoJson); - } - } - - // attribute list - else { - if (constraint) { - if (body.hasOwnProperty("ignoreNull")) { - index = collection.ensureGeoConstraint(fields[0], body.ignoreNull); - } - else { - index = collection.ensureGeoConstraint(fields[0], false); - } - } - else { - index = collection.ensureGeoIndex(fields[0]); - } - } - } - - // attributes - else if (fields.length === 2) { - if (constraint) { - if (body.hasOwnProperty("ignoreNull")) { - index = collection.ensureGeoConstraint(fields[0], fields[1], body.ignoreNull); - } - else { - index = collection.ensureGeoConstraint(fields[0], fields[1], false); - } - } - else { - index = collection.ensureGeoIndex(fields[0], fields[1]); - } - } - - // something is wrong - else { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "fields must be a list of attribute paths of length 1 or 2: " + fields); - return; - } - - if (index.isNewlyCreated) { - actions.resultOk(req, res, actions.HTTP_CREATED, index); - } - else { - actions.resultOk(req, res, actions.HTTP_OK, index); - } -} - //////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_post_api_index_hash /// @brief creates a hash index /// /// @RESTHEADER{POST /_api/index,creates a hash index} @@ -559,33 +441,8 @@ function post_api_index_geo (req, res, collection, body) { /// @END_EXAMPLE_ARANGOSH_RUN //////////////////////////////////////////////////////////////////////////////// -function post_api_index_hash (req, res, collection, body) { - var fields = body.fields; - - if (! (fields instanceof Array)) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "fields must be a list of attribute names: " + fields); - return; - } - - var index; - - if (body.unique) { - index = collection.ensureUniqueConstraint.apply(collection, fields); - } - else { - index = collection.ensureHashIndex.apply(collection, fields); - } - - if (index.isNewlyCreated) { - actions.resultOk(req, res, actions.HTTP_CREATED, index); - } - else { - actions.resultOk(req, res, actions.HTTP_OK, index); - } -} - //////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_post_api_index_skiplist /// @brief creates a skip-list /// /// @RESTHEADER{POST /_api/index,creates a skip list} @@ -647,33 +504,8 @@ function post_api_index_hash (req, res, collection, body) { /// @END_EXAMPLE_ARANGOSH_RUN //////////////////////////////////////////////////////////////////////////////// -function post_api_index_skiplist (req, res, collection, body) { - var fields = body.fields; - - if (! (fields instanceof Array)) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "fields must be a list of attribute names: " + fields); - return; - } - - var index; - - if (body.unique) { - index = collection.ensureUniqueSkiplist.apply(collection, fields); - } - else { - index = collection.ensureSkiplist.apply(collection, fields); - } - - if (index.isNewlyCreated) { - actions.resultOk(req, res, actions.HTTP_CREATED, index); - } - else { - actions.resultOk(req, res, actions.HTTP_OK, index); - } -} - //////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_post_api_index_fulltext /// @brief creates a fulltext index /// /// @RESTHEADER{POST /_api/index,creates a fulltext index} @@ -734,38 +566,8 @@ function post_api_index_skiplist (req, res, collection, body) { /// @END_EXAMPLE_ARANGOSH_RUN //////////////////////////////////////////////////////////////////////////////// -function post_api_index_fulltext (req, res, collection, body) { - var fields = body.fields; - - if (! (fields instanceof Array)) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "fields must be a list of attribute names: " + fields); - return; - } - - if (fields.length !== 1 || typeof fields[0] !== 'string') { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "fields must contain exactly one attribute name"); - return; - } - - if (body.hasOwnProperty("unique") && body.unique) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "unique fulltext indexes are not supported"); - return; - } - - var index = collection.ensureFulltextIndex.call(collection, fields, body.minLength || undefined); - - if (index.isNewlyCreated) { - actions.resultOk(req, res, actions.HTTP_CREATED, index); - } - else { - actions.resultOk(req, res, actions.HTTP_OK, index); - } -} - //////////////////////////////////////////////////////////////////////////////// +/// @fn JSF_post_api_index_bitarray /// @brief creates a bitarray /// /// @RESTHEADER{POST /_api/index,creates a bitarray index} @@ -826,32 +628,6 @@ function post_api_index_fulltext (req, res, collection, body) { /// @END_EXAMPLE_ARANGOSH_RUN //////////////////////////////////////////////////////////////////////////////// -function post_api_index_bitarray (req, res, collection, body) { - var fields = body.fields; - - if (! (fields instanceof Array)) { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "fields must be a list of attribute paths: " + fields); - return; - } - - var index; - - if (body["undefined"]) { - index = collection.ensureUndefBitarray.apply(collection, fields); - } - else { - index = collection.ensureBitarray.apply(collection, fields); - } - - if (index.isNewlyCreated) { - actions.resultOk(req, res, actions.HTTP_CREATED, index); - } - else { - actions.resultOk(req, res, actions.HTTP_OK, index); - } -} - //////////////////////////////////////////////////////////////////////////////// /// @brief creates an index /// @@ -859,14 +635,14 @@ function post_api_index_bitarray (req, res, collection, body) { /// /// @RESTQUERYPARAMETERS /// -/// @RESTQUERYPARAM{collection-name,string,required} +/// @RESTQUERYPARAM{collection,string,required} /// The collection name. /// /// @RESTBODYPARAM{index-details,json,required} /// /// @RESTDESCRIPTION /// -/// Creates a new index in the collection `collection-name`. Expects +/// Creates a new index in the collection `collection`. Expects /// an object containing the index details. /// /// The type of the index to be created must specified in the `type` @@ -896,19 +672,23 @@ function post_api_index_bitarray (req, res, collection, body) { /// the `unique` attribute with these types may lead to an error: /// - cap constraints /// - fulltext indexes +/// - bitarray indexes /// /// @RESTRETURNCODES /// /// @RESTRETURNCODE{200} -/// If the index already exists, then a `HTTP 200` is -/// returned. +/// If the index already exists, then an `HTTP 200` is returned. /// /// @RESTRETURNCODE{201} -/// If the index does not already exist and could be created, then a `HTTP 201` +/// If the index does not already exist and could be created, then an `HTTP 201` /// is returned. /// +/// @RESTRETURNCODE{400} +/// If an invalid index description is posted or attributes are used that the +/// target index will not support, then an `HTTP 400` is returned. +/// /// @RESTRETURNCODE{404} -/// If the `collection-name` is unknown, then a `HTTP 404` is returned. +/// If `collection` is unknown, then an `HTTP 404` is returned. //////////////////////////////////////////////////////////////////////////////// function post_api_index (req, res) { @@ -931,28 +711,40 @@ function post_api_index (req, res) { if (body === undefined) { return; } - - if (body.type === "cap") { - post_api_index_cap(req, res, collection, body); + + // inject collection name into body + if (body.collection === undefined) { + body.collection = name; } - else if (body.type === "geo") { - post_api_index_geo(req, res, collection, body); + + // fill "unique" attribute from "constraint" attribute to be downward-compatible + // with old geo index API + if (body.hasOwnProperty("constraint") && ! body.hasOwnProperty("unique")) { + body.unique = body.constraint; } - else if (body.type === "hash") { - post_api_index_hash(req, res, collection, body); + + // rewrite bitarray fields + if (body.type === "bitarray") { + if (typeof body.fields === "object" && + Array.isArray(body.fields) && + body.fields.length > 0) { + if (! Array.isArray(body.fields[0])) { + var f = [ ], i; + for (i = 0; i < body.fields.length; i += 2) { + f.push([ body.fields[i], body.fields[i + 1] ]); + } + body.fields = f; + } + } } - else if (body.type === "skiplist") { - post_api_index_skiplist(req, res, collection, body); - } - else if (body.type === "fulltext") { - post_api_index_fulltext(req, res, collection, body); - } - else if (body.type === "bitarray") { - post_api_index_bitarray(req, res, collection, body); + + // create the index + var index = collection.ensureIndex(body); + if (index.isNewlyCreated) { + actions.resultOk(req, res, actions.HTTP_CREATED, index); } else { - actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER, - "unknown index type '" + body.type + "'"); + actions.resultOk(req, res, actions.HTTP_OK, index); } } diff --git a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/arango-collection.js b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/arango-collection.js index ab91b3ac9c..0827267c37 100644 --- a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/arango-collection.js +++ b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/arango-collection.js @@ -623,15 +623,10 @@ ArangoCollection.prototype.dropIndex = function (id) { //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureBitarray = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "bitarray", unique : false, fields : fields }; + var body = { + type : "bitarray", + fields : Array.prototype.slice.call(arguments) + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -645,15 +640,11 @@ ArangoCollection.prototype.ensureBitarray = function () { //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureUndefBitarray = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "bitarray", unique : false, fields : fields, "undefined" : true }; + var body = { + type : "bitarray", + fields : Array.prototype.slice.call(arguments), + "undefined" : true + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -663,13 +654,11 @@ ArangoCollection.prototype.ensureUndefBitarray = function () { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a cap constraint +/// @brief ensures a cap constraint //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureCapConstraint = function (size, byteSize) { - var body; - - body = { + var body = { type : "cap", size : size || undefined, byteSize: byteSize || undefined @@ -683,61 +672,14 @@ ArangoCollection.prototype.ensureCapConstraint = function (size, byteSize) { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a unique skip-list index +/// @brief ensures a unique skip-list index //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureUniqueSkiplist = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "skiplist", unique : true, fields : fields }; - - var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); - - arangosh.checkRequestResult(requestResult); - - return requestResult; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds a skip-list index -//////////////////////////////////////////////////////////////////////////////// - -ArangoCollection.prototype.ensureSkiplist = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "skiplist", unique : false, fields : fields }; - - var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); - - arangosh.checkRequestResult(requestResult); - - return requestResult; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds a fulltext index -//////////////////////////////////////////////////////////////////////////////// - -ArangoCollection.prototype.ensureFulltextIndex = function (attribute, minLength) { - var minLengthValue = minLength || undefined; - var body; - - body = { - type: "fulltext", - minLength: minLengthValue, - fields: [ attribute ] + var body = { + type : "skiplist", + unique : true, + fields : Array.prototype.slice.call(arguments) }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -748,19 +690,51 @@ ArangoCollection.prototype.ensureFulltextIndex = function (attribute, minLength) }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a unique constraint +/// @brief ensures a skip-list index +//////////////////////////////////////////////////////////////////////////////// + +ArangoCollection.prototype.ensureSkiplist = function () { + var body = { + type : "skiplist", + unique : false, + fields : Array.prototype.slice.call(arguments) + }; + + var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); + + arangosh.checkRequestResult(requestResult); + + return requestResult; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief ensures a fulltext index +//////////////////////////////////////////////////////////////////////////////// + +ArangoCollection.prototype.ensureFulltextIndex = function (field, minLength) { + var body = { + type: "fulltext", + minLength: minLength || undefined, + fields: [ field ] + }; + + var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); + + arangosh.checkRequestResult(requestResult); + + return requestResult; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief ensures a unique constraint //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureUniqueConstraint = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "hash", unique : true, fields : fields }; + var body = { + type : "hash", + unique : true, + fields : Array.prototype.slice.call(arguments) + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -770,19 +744,15 @@ ArangoCollection.prototype.ensureUniqueConstraint = function () { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a hash index +/// @brief ensures a hash index //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureHashIndex = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "hash", unique : false, fields : fields }; + var body = { + type : "hash", + unique : false, + fields : Array.prototype.slice.call(arguments) + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -792,7 +762,7 @@ ArangoCollection.prototype.ensureHashIndex = function () { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds an geo index +/// @brief ensures a geo index //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) { @@ -834,7 +804,7 @@ ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds an geo constraint +/// @brief ensures a geo constraint //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) { @@ -886,6 +856,22 @@ ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) return requestResult; }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief ensures an index +//////////////////////////////////////////////////////////////////////////////// + +ArangoCollection.prototype.ensureIndex = function (data) { + if (typeof data !== "object" || Array.isArray(data)) { + throw "usage: ensureIndex()"; + } + + var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(data)); + + arangosh.checkRequestResult(requestResult); + + return requestResult; +}; + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/js/client/modules/org/arangodb/arango-collection.js b/js/client/modules/org/arangodb/arango-collection.js index 9ff4f46792..faf626cec2 100644 --- a/js/client/modules/org/arangodb/arango-collection.js +++ b/js/client/modules/org/arangodb/arango-collection.js @@ -622,15 +622,10 @@ ArangoCollection.prototype.dropIndex = function (id) { //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureBitarray = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "bitarray", unique : false, fields : fields }; + var body = { + type : "bitarray", + fields : Array.prototype.slice.call(arguments) + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -644,15 +639,11 @@ ArangoCollection.prototype.ensureBitarray = function () { //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureUndefBitarray = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "bitarray", unique : false, fields : fields, "undefined" : true }; + var body = { + type : "bitarray", + fields : Array.prototype.slice.call(arguments), + "undefined" : true + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -662,13 +653,11 @@ ArangoCollection.prototype.ensureUndefBitarray = function () { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a cap constraint +/// @brief ensures a cap constraint //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureCapConstraint = function (size, byteSize) { - var body; - - body = { + var body = { type : "cap", size : size || undefined, byteSize: byteSize || undefined @@ -682,61 +671,14 @@ ArangoCollection.prototype.ensureCapConstraint = function (size, byteSize) { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a unique skip-list index +/// @brief ensures a unique skip-list index //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureUniqueSkiplist = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "skiplist", unique : true, fields : fields }; - - var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); - - arangosh.checkRequestResult(requestResult); - - return requestResult; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds a skip-list index -//////////////////////////////////////////////////////////////////////////////// - -ArangoCollection.prototype.ensureSkiplist = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "skiplist", unique : false, fields : fields }; - - var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); - - arangosh.checkRequestResult(requestResult); - - return requestResult; -}; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief adds a fulltext index -//////////////////////////////////////////////////////////////////////////////// - -ArangoCollection.prototype.ensureFulltextIndex = function (attribute, minLength) { - var minLengthValue = minLength || undefined; - var body; - - body = { - type: "fulltext", - minLength: minLengthValue, - fields: [ attribute ] + var body = { + type : "skiplist", + unique : true, + fields : Array.prototype.slice.call(arguments) }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -747,19 +689,51 @@ ArangoCollection.prototype.ensureFulltextIndex = function (attribute, minLength) }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a unique constraint +/// @brief ensures a skip-list index +//////////////////////////////////////////////////////////////////////////////// + +ArangoCollection.prototype.ensureSkiplist = function () { + var body = { + type : "skiplist", + unique : false, + fields : Array.prototype.slice.call(arguments) + }; + + var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); + + arangosh.checkRequestResult(requestResult); + + return requestResult; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief ensures a fulltext index +//////////////////////////////////////////////////////////////////////////////// + +ArangoCollection.prototype.ensureFulltextIndex = function (field, minLength) { + var body = { + type: "fulltext", + minLength: minLength || undefined, + fields: [ field ] + }; + + var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); + + arangosh.checkRequestResult(requestResult); + + return requestResult; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief ensures a unique constraint //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureUniqueConstraint = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "hash", unique : true, fields : fields }; + var body = { + type : "hash", + unique : true, + fields : Array.prototype.slice.call(arguments) + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -769,19 +743,15 @@ ArangoCollection.prototype.ensureUniqueConstraint = function () { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds a hash index +/// @brief ensures a hash index //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureHashIndex = function () { - var i; - var body; - var fields = []; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - - body = { type : "hash", unique : false, fields : fields }; + var body = { + type : "hash", + unique : false, + fields : Array.prototype.slice.call(arguments) + }; var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(body)); @@ -791,7 +761,7 @@ ArangoCollection.prototype.ensureHashIndex = function () { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds an geo index +/// @brief ensures a geo index //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) { @@ -833,7 +803,7 @@ ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) { }; //////////////////////////////////////////////////////////////////////////////// -/// @brief adds an geo constraint +/// @brief ensures a geo constraint //////////////////////////////////////////////////////////////////////////////// ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) { @@ -885,6 +855,22 @@ ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) return requestResult; }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief ensures an index +//////////////////////////////////////////////////////////////////////////////// + +ArangoCollection.prototype.ensureIndex = function (data) { + if (typeof data !== "object" || Array.isArray(data)) { + throw "usage: ensureIndex()"; + } + + var requestResult = this._database._connection.POST(this._indexurl(), JSON.stringify(data)); + + arangosh.checkRequestResult(requestResult); + + return requestResult; +}; + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/js/server/tests/shell-index-ensure.js b/js/common/tests/shell-index-ensure.js similarity index 100% rename from js/server/tests/shell-index-ensure.js rename to js/common/tests/shell-index-ensure.js diff --git a/js/server/modules/org/arangodb/arango-collection.js b/js/server/modules/org/arangodb/arango-collection.js index cf50356655..e9a1a2e7ca 100644 --- a/js/server/modules/org/arangodb/arango-collection.js +++ b/js/server/modules/org/arangodb/arango-collection.js @@ -830,7 +830,7 @@ ArangoCollection.prototype.ensureBitarray = function () { return this.ensureIndex({ type: "bitarray", - fields: fields + fields : fields }); }; @@ -927,15 +927,9 @@ ArangoCollection.prototype.ensureCapConstraint = function (size, byteSize) { ArangoCollection.prototype.ensureUniqueSkiplist = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.ensureIndex({ type: "skiplist", - fields: fields, + fields: Array.prototype.slice.call(arguments), unique: true }); }; @@ -959,15 +953,9 @@ ArangoCollection.prototype.ensureUniqueSkiplist = function () { ArangoCollection.prototype.ensureSkiplist = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.ensureIndex({ type: "skiplist", - fields: fields + fields: Array.prototype.slice.call(arguments) }); }; @@ -992,17 +980,17 @@ ArangoCollection.prototype.ensureSkiplist = function () { /// @verbinclude fulltext //////////////////////////////////////////////////////////////////////////////// -ArangoCollection.prototype.ensureFulltextIndex = function (fields, minLength) { +ArangoCollection.prototype.ensureFulltextIndex = function (field, minLength) { "use strict"; - if (! Array.isArray(fields)) { - fields = [ fields ]; + if (! Array.isArray(field)) { + field = [ field ]; } return this.ensureIndex({ type: "fulltext", minLength: minLength || undefined, - fields: fields + fields: field }); }; @@ -1034,15 +1022,9 @@ ArangoCollection.prototype.ensureFulltextIndex = function (fields, minLength) { ArangoCollection.prototype.ensureUniqueConstraint = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.ensureIndex({ type: "hash", - fields: fields, + fields: Array.prototype.slice.call(arguments), unique: true }); }; @@ -1069,15 +1051,9 @@ ArangoCollection.prototype.ensureUniqueConstraint = function () { ArangoCollection.prototype.ensureHashIndex = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.ensureIndex({ type: "hash", - fields: fields + fields: Array.prototype.slice.call(arguments) }); }; @@ -1215,15 +1191,9 @@ ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull) ArangoCollection.prototype.lookupUniqueConstraint = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.lookupIndex({ type: "hash", - fields: fields, + fields: Array.prototype.slice.call(arguments), unique: true }); }; @@ -1235,15 +1205,9 @@ ArangoCollection.prototype.lookupUniqueConstraint = function () { ArangoCollection.prototype.lookupHashIndex = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.lookupIndex({ type: "hash", - fields: fields + fields: Array.prototype.slice.call(arguments) }); }; @@ -1254,15 +1218,9 @@ ArangoCollection.prototype.lookupHashIndex = function () { ArangoCollection.prototype.lookupUniqueSkiplist = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.lookupIndex({ type: "skiplist", - fields: fields, + fields: Array.prototype.slice.call(arguments), unique: true }); }; @@ -1274,15 +1232,9 @@ ArangoCollection.prototype.lookupUniqueSkiplist = function () { ArangoCollection.prototype.lookupSkiplist = function () { "use strict"; - var fields = [], i; - - for (i = 0; i < arguments.length; ++i) { - fields.push(arguments[i]); - } - return this.lookupIndex({ type: "skiplist", - fields: fields + fields: Array.prototype.slice.call(arguments) }); }; @@ -1294,16 +1246,16 @@ ArangoCollection.prototype.lookupSkiplist = function () { /// Checks whether a fulltext index on the given attribute @FA{field} exists. //////////////////////////////////////////////////////////////////////////////// -ArangoCollection.prototype.lookupFulltextIndex = function (fields, minLength) { +ArangoCollection.prototype.lookupFulltextIndex = function (field, minLength) { "use strict"; - if (! Array.isArray(fields)) { - fields = [ fields ]; + if (! Array.isArray(field)) { + field = [ field ]; } return this.lookupIndex({ type: "fulltext", - fields: fields, + fields: field, minLength: minLength || undefined }); };