1
0
Fork 0
arangodb/js/server/modules/@arangodb/arango-collection.js

954 lines
30 KiB
JavaScript

/*jshint strict: false */
/*global ArangoClusterComm, ArangoClusterInfo, require, exports, module */
////////////////////////////////////////////////////////////////////////////////
/// @brief ArangoCollection
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2011-2013 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
module.isSystem = true;
var internal = require("internal");
////////////////////////////////////////////////////////////////////////////////
/// @brief builds an example query
////////////////////////////////////////////////////////////////////////////////
function buildExampleQuery (collection, example, limit) {
var parts = [ ];
var bindVars = { "@collection" : collection.name() };
var keys = Object.keys(example);
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
parts.push("doc.@att" + i + " == @value" + i);
bindVars["att" + i] = key;
bindVars["value" + i] = example[key];
}
var query = "FOR doc IN @@collection";
if (parts.length > 0) {
query += " FILTER " + parts.join(" && ", parts);
}
if (limit > 0) {
query += " LIMIT " + parseInt(limit, 10);
}
return { query: query, bindVars: bindVars };
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add options from arguments to index specification
////////////////////////////////////////////////////////////////////////////////
function addIndexOptions (body, parameters) {
body.fields = [ ];
var setOption = function(k) {
if (! body.hasOwnProperty(k)) {
body[k] = parameters[i][k];
}
};
var i;
for (i = 0; i < parameters.length; ++i) {
if (typeof parameters[i] === "string") {
// set fields
body.fields.push(parameters[i]);
}
else if (typeof parameters[i] === "object" &&
! Array.isArray(parameters[i]) &&
parameters[i] !== null) {
// set arbitrary options
Object.keys(parameters[i]).forEach(setOption);
break;
}
}
return body;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor
////////////////////////////////////////////////////////////////////////////////
var ArangoCollection = internal.ArangoCollection;
exports.ArangoCollection = ArangoCollection;
// must be called after exporting ArangoCollection
require("@arangodb/arango-collection-common");
var simple = require("@arangodb/simple-query");
var ArangoError = require("@arangodb").ArangoError;
var ArangoDatabase = require("@arangodb/arango-database").ArangoDatabase;
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionToArray
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.toArray = function () {
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
return this.all().toArray();
}
return this.ALL(null, null).documents;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionTruncate
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.truncate = function () {
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
if (this.status() === ArangoCollection.STATUS_UNLOADED) {
this.load();
}
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, this.name());
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
shards.forEach(function (shard) {
ArangoClusterComm.asyncRequest("put",
"shard:" + shard,
dbName,
"/_api/collection/" + encodeURIComponent(shard) + "/truncate",
"",
{ },
options);
});
cluster.wait(coord, shards);
return;
}
return this.TRUNCATE();
};
////////////////////////////////////////////////////////////////////////////////
/// @brief finds an index of a collection
///
/// @FUN{@FA{collection}.index(@FA{index-handle})}
///
/// Returns the index with @FA{index-handle} or null if no such index exists.
///
/// *Examples*
///
/// @code
/// arango> db.example.getIndexes().map(function(x) { return x.id; });
/// ["example/0"]
/// arango> db.example.index("93013/0");
/// { "id" : "example/0", "type" : "primary", "fields" : ["_id"] }
/// @endcode
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.index = function (id) {
var indexes = this.getIndexes();
var i;
if (typeof id === "object" && id.hasOwnProperty("id")) {
id = id.id;
}
if (typeof id === "string") {
var pa = ArangoDatabase.indexRegex.exec(id);
if (pa === null) {
id = this.name() + "/" + id;
}
}
else if (typeof id === "number") {
// stringify the id
id = this.name() + "/" + id;
}
for (i = 0; i < indexes.length; ++i) {
var index = indexes[i];
if (index.id === id) {
return index;
}
}
var err = new ArangoError();
err.errorNum = internal.errors.ERROR_ARANGO_INDEX_NOT_FOUND.code;
err.errorMessage = internal.errors.ERROR_ARANGO_INDEX_NOT_FOUND.message;
throw err;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief returns connected edges
////////////////////////////////////////////////////////////////////////////////
function getEdges (collection, vertex, direction) {
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, collection.name());
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
var body;
if (vertex !== null &&
typeof vertex === "object" &&
vertex.hasOwnProperty("_id")) {
vertex = vertex._id;
}
if (Array.isArray(vertex)) {
var idList = vertex.map(function (v) {
if (v !== null) {
if (typeof v === "object" &&
v.hasOwnProperty("_id")) {
return v._id;
}
if (typeof v === "string") {
return v;
}
}
});
body = JSON.stringify(idList);
shards.forEach(function (shard) {
var url = "/_api/edges/" + encodeURIComponent(shard) +
"?direction=" + encodeURIComponent(direction);
ArangoClusterComm.asyncRequest("post",
"shard:" + shard,
dbName,
url,
body,
{ },
options);
});
}
else {
shards.forEach(function (shard) {
var url = "/_api/edges/" + encodeURIComponent(shard) +
"?direction=" + encodeURIComponent(direction) +
"&vertex=" + encodeURIComponent(vertex);
ArangoClusterComm.asyncRequest("get",
"shard:" + shard,
dbName,
url,
"",
{ },
options);
});
}
var results = cluster.wait(coord, shards), i;
var edges = [ ];
for (i = 0; i < results.length; ++i) {
body = JSON.parse(results[i].body);
edges = edges.concat(body.edges);
}
return edges;
}
if (direction === "in") {
return collection.INEDGES(vertex);
}
if (direction === "out") {
return collection.OUTEDGES(vertex);
}
return collection.EDGES(vertex);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionEdgesAll
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.edges = function (vertex) {
return getEdges(this, vertex, "any");
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionEdgesInbound
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.inEdges = function (vertex) {
return getEdges(this, vertex, "in");
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionEdgesOutbound
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.outEdges = function (vertex) {
return getEdges(this, vertex, "out");
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock documentsCollectionAny
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.any = function () {
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, this.name());
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
shards.forEach(function (shard) {
ArangoClusterComm.asyncRequest("put",
"shard:" + shard,
dbName,
"/_api/simple/any",
JSON.stringify({
collection: shard
}),
{ },
options);
});
var results = cluster.wait(coord, shards), i;
for (i = 0; i < results.length; ++i) {
var body = JSON.parse(results[i].body);
if (body.document !== null) {
return body.document;
}
}
return null;
}
return this.ANY();
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock documentsCollectionFirst
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.first = function (count) {
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, this.name());
if (shards.length !== 1) {
var err = new ArangoError();
err.errorNum = internal.errors.ERROR_CLUSTER_UNSUPPORTED.code;
err.errorMessage = "operation is not supported in sharded collections";
throw err;
}
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
var shard = shards[0];
ArangoClusterComm.asyncRequest("put",
"shard:" + shard,
dbName,
"/_api/simple/first",
JSON.stringify({
collection: shard,
count: count
}),
{ },
options);
var results = cluster.wait(coord, shards);
if (results.length) {
var body = JSON.parse(results[0].body);
return body.result || null;
}
}
else {
return this.FIRST(count);
}
return null;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock documentsCollectionLast
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.last = function (count) {
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, this.name());
if (shards.length !== 1) {
var err = new ArangoError();
err.errorNum = internal.errors.ERROR_CLUSTER_UNSUPPORTED.code;
err.errorMessage = "operation is not supported in sharded collections";
throw err;
}
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
var shard = shards[0];
ArangoClusterComm.asyncRequest("put",
"shard:" + shard,
dbName,
"/_api/simple/last",
JSON.stringify({
collection: shard,
count: count
}),
{ },
options);
var results = cluster.wait(coord, shards);
if (results.length) {
var body = JSON.parse(results[0].body);
return body.result || null;
}
}
else {
return this.LAST(count);
}
return null;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionFirstExample
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.firstExample = function (example) {
var e;
var i;
// example is given as only argument
if (arguments.length === 1) {
e = example;
}
// example is given as list
else {
e = {};
for (i = 0; i < arguments.length; i += 2) {
e[arguments[i]] = arguments[i + 1];
}
}
var documents = (new simple.SimpleQueryByExample(this, e)).limit(1).toArray();
if (documents.length > 0) {
return documents[0];
}
return null;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief removes documents matching an example
/// @param example a json object which is used as sample for finding docs that
/// this example matches
/// @param waitForSync (optional) a boolean value or a json object
/// @param limit (optional) an integer value, the max number of to deleting docs
/// @example remove("{a : 1 }")
/// @example remove("{a : 1 }", true)
/// @example remove("{a : 1 }", false)
/// @example remove("{a : 1 }", {waitForSync: false, limit: 12})
/// @throws "too many parameters" when waiitForSyn is a Json object and limit
/// is given
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.removeByExample = function (example,
waitForSync,
limit) {
if (limit === 0) {
return 0;
}
if (typeof waitForSync === "object") {
if (typeof limit !== "undefined") {
throw "too many parameters";
}
var tmp_options = waitForSync === null ? {} : waitForSync;
// avoiding jslint error
// see: http://jslinterrors.com/unexpected-sync-method-a/
waitForSync = tmp_options.waitForSync;
limit = tmp_options.limit;
}
var i;
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, this.name());
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
if (limit > 0 && shards.length > 1) {
var err = new ArangoError();
err.errorNum = internal.errors.ERROR_CLUSTER_UNSUPPORTED.code;
err.errorMessage = "limit is not supported in sharded collections";
throw err;
}
shards.forEach(function (shard) {
ArangoClusterComm.asyncRequest("put",
"shard:" + shard,
dbName,
"/_api/simple/remove-by-example",
JSON.stringify({
collection: shard,
example: example,
waitForSync: waitForSync,
limit: limit || undefined
}),
{ },
options);
});
var deleted = 0;
var results = cluster.wait(coord, shards);
for (i = 0; i < results.length; ++i) {
var body = JSON.parse(results[i].body);
deleted += (body.deleted || 0);
}
return deleted;
}
var query = buildExampleQuery(this, example, limit);
var opts = { waitForSync : waitForSync };
query.query += " REMOVE doc IN @@collection OPTIONS " + JSON.stringify(opts);
return require("internal").db._query(query).getExtra().stats.writesExecuted;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief replaces documents matching an example
/// @param example the json object for finding documents which matches this
/// example
/// @param newValue the json object which replaces the matched documents
/// @param waitForSync (optional) a boolean value or a json object which
/// contains the options
/// @param limit (optional) an integer value, the max number of to deleting docs
/// @throws "too many parameters" when waitForSync is a json object and limit
/// was given
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.replaceByExample = function (example,
newValue,
waitForSync,
limit) {
if (limit === 0) {
return 0;
}
if (typeof newValue !== "object" || Array.isArray(newValue)) {
var err1 = new ArangoError();
err1.errorNum = internal.errors.ERROR_BAD_PARAMETER.code;
err1.errorMessage = "invalid value for parameter 'newValue'";
throw err1;
}
if (typeof waitForSync === "object") {
if (typeof limit !== "undefined") {
throw "too many parameters";
}
var tmp_options = waitForSync === null ? {} : waitForSync;
// avoiding jslint error
// see: http://jslinterrors.com/unexpected-sync-method-a/
waitForSync = tmp_options.waitForSync;
limit = tmp_options.limit;
}
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, this.name());
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
if (limit > 0 && shards.length > 1) {
var err2 = new ArangoError();
err2.errorNum = internal.errors.ERROR_CLUSTER_UNSUPPORTED.code;
err2.errorMessage = "limit is not supported in sharded collections";
throw err2;
}
shards.forEach(function (shard) {
ArangoClusterComm.asyncRequest("put",
"shard:" + shard,
dbName,
"/_api/simple/replace-by-example",
JSON.stringify({
collection: shard,
example: example,
newValue: newValue,
waitForSync: waitForSync,
limit: limit || undefined
}),
{ },
options);
});
var replaced = 0;
var results = cluster.wait(coord, shards), i;
for (i = 0; i < results.length; ++i) {
var body = JSON.parse(results[i].body);
replaced += (body.replaced || 0);
}
return replaced;
}
var query = buildExampleQuery(this, example, limit);
var opts = { waitForSync : waitForSync };
query.query += " REPLACE doc WITH @newValue IN @@collection OPTIONS " + JSON.stringify(opts);
query.bindVars.newValue = newValue;
return require("internal").db._query(query).getExtra().stats.writesExecuted;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief partially updates documents matching an example
/// @param example the json object for finding documents which matches this
/// example
/// @param newValue the json object which replaces the matched documents
/// @param keepNull (optional) true or a JSON object which
/// contains the options
/// @param waitForSync (optional) a boolean value
/// @param limit (optional) an integer value, the max number of to deleting docs
/// @throws "too many parameters" when keepNull is a JSON object and limit
/// was given
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.updateByExample = function (example,
newValue,
keepNull,
waitForSync,
limit) {
if (limit === 0) {
return 0;
}
if (typeof newValue !== "object" || Array.isArray(newValue)) {
var err1 = new ArangoError();
err1.errorNum = internal.errors.ERROR_BAD_PARAMETER.code;
err1.errorMessage = "invalid value for parameter 'newValue'";
throw err1;
}
var mergeObjects = true;
if (typeof keepNull === "object") {
if (typeof waitForSync !== "undefined") {
throw "too many parameters";
}
var tmp_options = keepNull === null ? {} : keepNull;
// avoiding jslint error
// see: http://jslinterrors.com/unexpected-sync-method-a/
keepNull = tmp_options.keepNull;
waitForSync = tmp_options.waitForSync;
limit = tmp_options.limit;
if (tmp_options.hasOwnProperty("mergeObjects")) {
mergeObjects = tmp_options.mergeObjects || false;
}
}
var cluster = require("@arangodb/cluster");
if (cluster.isCoordinator()) {
var dbName = require("internal").db._name();
var shards = cluster.shardList(dbName, this.name());
var coord = { coordTransactionID: ArangoClusterInfo.uniqid() };
var options = { coordTransactionID: coord.coordTransactionID, timeout: 360 };
if (limit > 0 && shards.length > 1) {
var err2 = new ArangoError();
err2.errorNum = internal.errors.ERROR_CLUSTER_UNSUPPORTED.code;
err2.errorMessage = "limit is not supported in sharded collections";
throw err2;
}
shards.forEach(function (shard) {
ArangoClusterComm.asyncRequest("put",
"shard:" + shard,
dbName,
"/_api/simple/update-by-example",
JSON.stringify({
collection: shard,
example: example,
newValue: newValue,
waitForSync: waitForSync,
keepNull: keepNull,
mergeObjects: mergeObjects,
limit: limit || undefined
}),
{ },
options);
});
var updated = 0;
var results = cluster.wait(coord, shards), i;
for (i = 0; i < results.length; ++i) {
var body = JSON.parse(results[i].body);
updated += (body.updated || 0);
}
return updated;
}
var query = buildExampleQuery(this, example, limit);
var opts = { waitForSync : waitForSync, keepNull: keepNull, mergeObjects: mergeObjects };
query.query += " UPDATE doc WITH @newValue IN @@collection OPTIONS " + JSON.stringify(opts);
query.bindVars.newValue = newValue;
return require("internal").db._query(query).getExtra().stats.writesExecuted;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionEnsureCapConstraint
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureCapConstraint = function (size, byteSize) {
'use strict';
return this.ensureIndex({
type: "cap",
size: size || undefined,
byteSize: byteSize || undefined
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock ensureUniqueSkiplist
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureUniqueSkiplist = function () {
'use strict';
return this.ensureIndex(addIndexOptions({
type: "skiplist",
unique: true
}, arguments));
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock ensureSkiplist
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureSkiplist = function () {
'use strict';
return this.ensureIndex(addIndexOptions({
type: "skiplist"
}, arguments));
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock ensureFulltextIndex
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureFulltextIndex = function (field, minLength) {
'use strict';
if (! Array.isArray(field)) {
field = [ field ];
}
return this.ensureIndex({
type: "fulltext",
minLength: minLength || undefined,
fields: field
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock ensureUniqueConstraint
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureUniqueConstraint = function () {
'use strict';
return this.ensureIndex(addIndexOptions({
type: "hash",
unique: true
}, arguments));
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock ensureHashIndex
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureHashIndex = function () {
'use strict';
return this.ensureIndex(addIndexOptions({
type: "hash"
}, arguments));
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionEnsureGeoIndex
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureGeoIndex = function (lat, lon) {
'use strict';
if (typeof lat !== "string") {
throw "usage: ensureGeoIndex(<lat>, <lon>) or ensureGeoIndex(<loc>[, <geoJson>])";
}
if (typeof lon === "boolean") {
return this.ensureIndex({
type : "geo1",
fields : [ lat ],
geoJson : lon
});
}
if (lon === undefined) {
return this.ensureIndex({
type : "geo1",
fields : [ lat ],
geoJson : false
});
}
return this.ensureIndex({
type : "geo2",
fields : [ lat, lon ]
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock collectionEnsureGeoConstraint
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon) {
'use strict';
return this.ensureGeoIndex(lat, lon);
};
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a unique constraint
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.lookupUniqueConstraint = function () {
'use strict';
return this.lookupIndex({
type: "hash",
fields: Array.prototype.slice.call(arguments),
unique: true
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a hash index
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.lookupHashIndex = function () {
'use strict';
return this.lookupIndex({
type: "hash",
fields: Array.prototype.slice.call(arguments)
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a unique skiplist index
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.lookupUniqueSkiplist = function () {
'use strict';
return this.lookupIndex({
type: "skiplist",
fields: Array.prototype.slice.call(arguments),
unique: true
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up a skiplist index
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.lookupSkiplist = function () {
'use strict';
return this.lookupIndex({
type: "skiplist",
fields: Array.prototype.slice.call(arguments)
});
};
////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock lookUpFulltextIndex
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.lookupFulltextIndex = function (field, minLength) {
'use strict';
if (! Array.isArray(field)) {
field = [ field ];
}
return this.lookupIndex({
type: "fulltext",
fields: field,
minLength: minLength || undefined
});
};