1
0
Fork 0

added skip list queries

This commit is contained in:
Frank Celler 2012-05-21 17:19:17 +02:00
parent b64a51844f
commit b682357901
13 changed files with 962 additions and 537 deletions

View File

@ -0,0 +1,6 @@
arangod> l = db.skip.closedRange("age", 10, 12).toArray();
[
{ "_id" : "2097590/4260278", "_rev" : 4260278, "age" : 10 },
{ "_id" : "2097590/4325814", "_rev" : 4325814, "age" : 11 },
{ "_id" : "2097590/4391350", "_rev" : 4391350, "age" : 12 }
]

View File

@ -0,0 +1,6 @@
arangod> l = db.skip.range("age", 10, 13).toArray();
[
{ "_id" : "2097590/4260278", "_rev" : 4260278, "age" : 10 },
{ "_id" : "2097590/4325814", "_rev" : 4325814, "age" : 11 },
{ "_id" : "2097590/4391350", "_rev" : 4391350, "age" : 12 }
]

View File

@ -868,7 +868,7 @@ int ArangoServer::executeShell (bool tests) {
char* input = console->prompt("arangod> ");
if (input == 0) {
printf("<ctrl-D>\nBye Bye! Auf Wiedersehen! さようなら\n");
printf("<ctrl-D>\nBye Bye! Auf Wiedersehen! До свидания! さようなら\n");
break;
}

View File

@ -414,6 +414,41 @@ function POST_api_index_hash (req, res, collection, body) {
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a skip-list
///
/// @RESTHEADER{POST /_api/index,creates a hash index}
///
/// @REST{POST /_api/index?collection=@FA{collection-identifier}}
///
/// Creates a skip-list index for the collection @FA{collection-identifier}, if
/// it does not already exist. The call expects an object containing the index
/// details.
///
/// - @LIT{type}: must be equal to @LIT{"skiplist"}.
///
/// - @LIT{fields}: A list of attribute paths.
///
/// - @LIT{unique}: If @LIT{true}, then create a unique index.
///
/// If the index does not already exists and could be created, then a @LIT{HTTP
/// 201} is returned. If the index already exists, then a @LIT{HTTP 200} is
/// returned.
///
/// If the @FA{collection-identifier} is unknown, then a @LIT{HTTP 404} is
/// returned. It is possible to specify a name instead of an identifier.
///
/// If the collection already contains documents and you try to create a unique
/// skip-list index in such a way that there are documents violating the
/// uniqueness, then a @LIT{HTTP 400} is returned.
///
/// @EXAMPLES
///
/// Creating an unique constraint:
///
/// @verbinclude api-index-create-new-unique-skiplist
///
/// Creating a hash index:
///
/// @verbinclude api-index-create-new-skiplist
////////////////////////////////////////////////////////////////////////////////
function POST_api_index_skiplist (req, res, collection, body) {

View File

@ -452,10 +452,6 @@ actions.defineHttp({
///
/// - @LIT{example}: The example.
///
/// - @LIT{skip}: The documents to skip in the query. (optional)
///
/// - @LIT{limit}: The maximal amount of documents to return. (optional)
///
/// Returns a result containing the document or @LIT{HTTP 404} if no
/// document matched the example.
///
@ -560,6 +556,99 @@ actions.defineHttp({
}
});
////////////////////////////////////////////////////////////////////////////////
/// @fn JSA_PUT_api_simple_range
/// @brief returns all documents of a collection within a range
///
/// @RESTHEADER{PUT /_api/simple/range,executes simple range query}
///
/// @REST{PUT /_api/simple/range}
///
/// This will find all documents within a given range.
///
/// The call expects a JSON hash array as body with the following attributes:
///
/// - @LIT{collection}: The identifier or name of the collection to query.
///
/// - @LIT{attribute}: The attribute path to check.
///
/// - @LIT{left}: The lower bound.
///
/// - @LIT{right}: The upper bound.
///
/// - @LIT{closed}: If true, use intervall including @LIT{left} and @LIT{right},
/// otherwise exclude @LIT{right}, but include @LIT{left}.
///
/// - @LIT{skip}: The documents to skip in the query. (optional)
///
/// - @LIT{limit}: The maximal amount of documents to return. (optional)
///
/// Returns a cursor containing the result, see @ref HttpCursor for details.
///
/// @EXAMPLES
///
/// @verbinclude api-simple-range
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url : API + "range",
context : "api",
callback : function (req, res) {
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (req.requestType != actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var limit = body.limit;
var skip = body.skip;
var name = body.collection;
var attribute = body.attribute;
var left = body.left;
var right = body.right;
var closed = body.closed;
var name = body.collection;
var id = parseInt(name) || name;
var collection = internal.db._collection(id);
if (collection == null) {
actions.collectionNotFound(req, res, name);
}
else {
try {
var result;
if (closed) {
result = collection.closedRange(attribute, left, right);
}
else {
result = collection.range(attribute, left, right);
}
if (skip != null) {
result = result.skip(skip);
}
if (limit != null) {
result = result.limit(limit);
}
actions.resultCursor(req, res, CREATE_CURSOR(result.toArray(), true));
}
catch (err) {
actions.resultException(req, res, err);
}
}
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -1237,6 +1237,48 @@ ArangoCollection.prototype.ensureCapConstraint = function (size) {
return requestResult;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a unique skip-list index
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureUniqueSkiplist = function () {
var body;
var fields = [];
for (var i = 0; i < arguments.length; ++i) {
fields.push(arguments[i]);
}
body = { type : "skiplist", unique : true, fields : fields };
var requestResult = this._database._connection.POST("/_api/index?collection=" + encodeURIComponent(this._id), JSON.stringify(body));
TRI_CheckRequestResult(requestResult);
return requestResult;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a skip-list index
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.ensureSkiplist = function () {
var body;
var fields = [];
for (var i = 0; i < arguments.length; ++i) {
fields.push(arguments[i]);
}
body = { type : "skiplist", unique : false, fields : fields };
var requestResult = this._database._connection.POST("/_api/index?collection=" + encodeURIComponent(this._id), JSON.stringify(body));
TRI_CheckRequestResult(requestResult);
return requestResult;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief adds a unique constraint
////////////////////////////////////////////////////////////////////////////////
@ -1279,35 +1321,6 @@ ArangoCollection.prototype.ensureHashIndex = function () {
return requestResult;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief queries by example
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.BY_EXAMPLE_HASH = function (index, example, skip, limit) {
var body;
limit = limit || null;
skip = skip || null;
if (index.hasOwnProperty("id")) {
index = index.id;
}
body = { collection : this._id, index : index, skip : skip, limit : limit, example : {} };
for (var key in example) {
if (example.hasOwnProperty(key)) {
body.example[key] = example[key];
}
}
var requestResult = this._database._connection.PUT("/_api/simple/BY-EXAMPLE-HASH", JSON.stringify(body));
TRI_CheckRequestResult(requestResult);
return requestResult;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief adds an geo index
////////////////////////////////////////////////////////////////////////////////
@ -1367,6 +1380,35 @@ ArangoCollection.prototype.ensureGeoConstraint = function (lat, lon, ignoreNull)
return requestResult;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief queries by example
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.BY_EXAMPLE_HASH = function (index, example, skip, limit) {
var body;
limit = limit || null;
skip = skip || null;
if (index.hasOwnProperty("id")) {
index = index.id;
}
body = { collection : this._id, index : index, skip : skip, limit : limit, example : {} };
for (var key in example) {
if (example.hasOwnProperty(key)) {
body.example[key] = example[key];
}
}
var requestResult = this._database._connection.PUT("/_api/simple/BY-EXAMPLE-HASH", JSON.stringify(body));
TRI_CheckRequestResult(requestResult);
return requestResult;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief truncates a collection
////////////////////////////////////////////////////////////////////////////////

View File

@ -1239,6 +1239,48 @@ static string JS_client_client =
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief adds a unique skip-list index\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"ArangoCollection.prototype.ensureUniqueSkiplist = function () {\n"
" var body;\n"
" var fields = [];\n"
" \n"
" for (var i = 0; i < arguments.length; ++i) {\n"
" fields.push(arguments[i]);\n"
" }\n"
"\n"
" body = { type : \"skiplist\", unique : true, fields : fields };\n"
"\n"
" var requestResult = this._database._connection.POST(\"/_api/index?collection=\" + encodeURIComponent(this._id), JSON.stringify(body));\n"
"\n"
" TRI_CheckRequestResult(requestResult);\n"
"\n"
" return requestResult;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief adds a skip-list index\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"ArangoCollection.prototype.ensureSkiplist = function () {\n"
" var body;\n"
" var fields = [];\n"
" \n"
" for (var i = 0; i < arguments.length; ++i) {\n"
" fields.push(arguments[i]);\n"
" }\n"
"\n"
" body = { type : \"skiplist\", unique : false, fields : fields };\n"
"\n"
" var requestResult = this._database._connection.POST(\"/_api/index?collection=\" + encodeURIComponent(this._id), JSON.stringify(body));\n"
"\n"
" TRI_CheckRequestResult(requestResult);\n"
"\n"
" return requestResult;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief adds a unique constraint\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
@ -1281,35 +1323,6 @@ static string JS_client_client =
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief queries by example\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"ArangoCollection.prototype.BY_EXAMPLE_HASH = function (index, example, skip, limit) {\n"
" var body;\n"
"\n"
" limit = limit || null;\n"
" skip = skip || null;\n"
"\n"
" if (index.hasOwnProperty(\"id\")) {\n"
" index = index.id;\n"
" }\n"
"\n"
" body = { collection : this._id, index : index, skip : skip, limit : limit, example : {} };\n"
"\n"
" for (var key in example) {\n"
" if (example.hasOwnProperty(key)) {\n"
" body.example[key] = example[key];\n"
" }\n"
" }\n"
"\n"
" var requestResult = this._database._connection.PUT(\"/_api/simple/BY-EXAMPLE-HASH\", JSON.stringify(body));\n"
"\n"
" TRI_CheckRequestResult(requestResult);\n"
"\n"
" return requestResult;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief adds an geo index\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
@ -1369,6 +1382,35 @@ static string JS_client_client =
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief queries by example\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"ArangoCollection.prototype.BY_EXAMPLE_HASH = function (index, example, skip, limit) {\n"
" var body;\n"
"\n"
" limit = limit || null;\n"
" skip = skip || null;\n"
"\n"
" if (index.hasOwnProperty(\"id\")) {\n"
" index = index.id;\n"
" }\n"
"\n"
" body = { collection : this._id, index : index, skip : skip, limit : limit, example : {} };\n"
"\n"
" for (var key in example) {\n"
" if (example.hasOwnProperty(key)) {\n"
" body.example[key] = example[key];\n"
" }\n"
" }\n"
"\n"
" var requestResult = this._database._connection.PUT(\"/_api/simple/BY-EXAMPLE-HASH\", JSON.stringify(body));\n"
"\n"
" TRI_CheckRequestResult(requestResult);\n"
"\n"
" return requestResult;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief truncates a collection\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"

View File

@ -181,6 +181,59 @@ ArangoEdgesCollection.prototype.firstExample = ArangoCollection.prototype.firstE
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- RANGE QUERY
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief executes a range query
////////////////////////////////////////////////////////////////////////////////
SQ.SimpleQueryRange.prototype.execute = function () {
var documents;
if (this._execution == null) {
var data = {
collection : this._collection._id,
attribute : this._attribute,
right : this._right,
left : this._left,
closed : this._type == 1
}
if (this._limit != null) {
data.limit = this._limit;
}
if (this._skip != null) {
data.skip = this._skip;
}
var requestResult = this._collection._database._connection.PUT("/_api/simple/range", JSON.stringify(data));
TRI_CheckRequestResult(requestResult);
this._execution = new ArangoQueryCursor(this._collection._database, requestResult);
if (requestResult.hasOwnProperty("count")) {
this._countQuery = requestResult.count;
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- SIMPLE QUERY NEAR
// -----------------------------------------------------------------------------

View File

@ -29,318 +29,6 @@ var internal = require("internal");
var ArangoCollection = internal.ArangoCollection;
var ArangoEdgesCollection = internal.ArangoEdgesCollection;
// -----------------------------------------------------------------------------
// --SECTION-- ARANGO COLLECTION
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs an all query for a collection
///
/// @FUN{all()}
///
/// Selects all documents of a collection and returns a cursor. You can use
/// @FN{toArray}, @FN{next}, or @FN{hasNext} to access the result. The result
/// can be limited using the @FN{skip} and @FN{limit} operator.
///
/// @EXAMPLES
///
/// Use @FN{toArray} to get all documents at once:
///
/// @verbinclude simple3
///
/// Use @FN{next} to loop over all documents:
///
/// @verbinclude simple4
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.all = function () {
return new SimpleQueryAll(this);
}
ArangoEdgesCollection.prototype.all = ArangoCollection.prototype.all;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a near query for a collection
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude})}
/////////////////////////////////////////////////////////////
///
/// The default will find at most 100 documents near the coordinate
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted according to
/// the distance, with the nearest document coming first. If there are near
/// documents of equal distance, documents are chosen randomly from this set
/// until the limit is reached. It is possible to change the limit using the
/// @FA{limit} operator.
///
/// In order to use the @FN{near} operator, a geo index must be defined for the
/// collection. This index also defines which attribute holds the coordinates
/// for the document. If you have more then one geo-spatial index, you can use
/// the @FN{geo} operator to select a particular index.
///
/// @note @FN{near} does not support negative skips. However, you can still use
/// @FN{limit} followed to @FN{skip}.
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude}).limit(@FA{limit})}
///////////////////////////////////////////////////////////////////////////////
///
/// Limits the result to @FA{limit} documents instead of the default 100.
///
/// @note Unlike with multiple explicit limits, @FA{limit} will raise
/// the implicit default limit imposed by @FN{within}.
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude}).distance()}
////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @LIT{distance} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude}).distance(@FA{name})}
/////////////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @FA{name} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @EXAMPLES
///
/// To get the nearst two locations:
///
/// @TINYEXAMPLE{simple-query-near,nearest two location}
///
/// If you need the distance as well, then you can use the @FN{distance}
/// operator:
///
/// @TINYEXAMPLE{simple-query-near2,nearest two location with distance in meter}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.near = function (lat, lon) {
return new SimpleQueryNear(this, lat, lon);
}
ArangoEdgesCollection.prototype.near = ArangoCollection.prototype.near;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a within query for a collection
///
/// @FUN{@FA{collection}.within(@FA{latitude}, @FA{longitude}, @FA{radius})}
////////////////////////////////////////////////////////////////////////////
///
/// This will find all documents with in a given radius around the coordinate
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted by distance.
///
/// In order to use the @FN{within} operator, a geo index must be defined for the
/// collection. This index also defines which attribute holds the coordinates
/// for the document. If you have more then one geo-spatial index, you can use
/// the @FN{geo} operator to select a particular index.
///
/// @FUN{@FA{collection}.within(@FA{latitude}, @FA{longitude}, @FA{radius})@LATEXBREAK.distance()}
//////////////////////////////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @LIT{_distance} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @FUN{@FA{collection}.within(@FA{latitude}, @FA{longitude}, @FA{radius})@LATEXBREAK.distance(@FA{name})}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @FA{name} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @EXAMPLES
///
/// To find all documents within a radius of 2000 km use:
///
/// @TINYEXAMPLE{simple-query-within,within a radius}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.within = function (lat, lon, radius) {
return new SimpleQueryWithin(this, lat, lon, radius);
}
ArangoEdgesCollection.prototype.within = ArangoCollection.prototype.within;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a geo index selection
///
/// @FUN{@FA{collection}.geo(@FA{location})}
////////////////////////////////////////////
///
/// The next @FN{near} or @FN{within} operator will use the specific geo-spatial
/// index.
///
/// @FUN{@FA{collection}.geo(@FA{location}, @LIT{true})}
////////////////////////////////////////////////////////
///
/// The next @FN{near} or @FN{within} operator will use the specific geo-spatial
/// index.
///
/// @FUN{@FA{collection}.geo(@FA{latitude}, @FA{longitude})}
////////////////////////////////////////////////////////////
///
/// The next @FN{near} or @FN{within} operator will use the specific geo-spatial
/// index.
///
/// @EXAMPLES
///
/// Assume you have a location stored as list in the attribute @LIT{home}
/// and a destination stored in the attribute @LIT{work}. Than you can use the
/// @FN{geo} operator to select, which coordinates to use in a near query.
///
/// @TINYEXAMPLE{simple-query-geo,use a specific index}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.geo = function(loc, order) {
var idx;
var locateGeoIndex1 = function(collection, loc, order) {
var inds = collection.getIndexes();
for (var i = 0; i < inds.length; ++i) {
var index = inds[i];
if (index.type == "geo1") {
if (index.fields[0] == loc && index.geoJson == order) {
return index;
}
}
}
return null;
};
var locateGeoIndex2 = function(collection, lat, lon) {
var inds = collection.getIndexes();
for (var i = 0; i < inds.length; ++i) {
var index = inds[i];
if (index.type == "geo2") {
if (index.fields[0] == lat && index.fields[1] == lon) {
return index;
}
}
}
return null;
};
if (order === undefined) {
if (typeof loc === "object") {
idx = this.index(loc);
}
else {
idx = locateGeoIndex1(this, loc, false);
}
}
else if (typeof order === "boolean") {
idx = locateGeoIndex1(this, loc, order);
}
else {
idx = locateGeoIndex2(this, loc, order);
}
if (idx == null) {
var err = new ArangoError();
err.errorNum = internal.errors.ERROR_QUERY_GEO_INDEX_MISSING.code;
err.errorMessage = internal.errors.ERROR_QUERY_GEO_INDEX_MISSING.message;
throw err;
}
return new SimpleQueryGeo(this, idx.id);
}
ArangoEdgesCollection.prototype.geo = ArangoCollection.geo;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
///
/// @FUN{@FA{collection}.byExample(@FA{example})}
///
/// Selects all documents of a collection that match the specified
/// example and returns a cursor.
///
/// You can use @FN{toArray}, @FN{next}, or @FN{hasNext} to access the
/// result. The result can be limited using the @FN{skip} and @FN{limit}
/// operator.
///
/// An attribute name of the form @LIT{a.b} is interpreted as attribute path,
/// not as attribute. If you use
///
/// @LIT{{ a : { c : 1 } }}
///
/// as example, then you will find all documents, such that the attribute
/// @LIT{a} contains a document of the form @LIT{{c : 1 }}. E.g., the document
///
/// @LIT{{ a : { c : 1 }\, b : 1 }}
///
/// will match, but the document
///
/// @LIT{{ a : { c : 1\, b : 1 } }}
///
/// will not.
///
/// However, if you use
///
/// @LIT{{ a.c : 1 }},
///
/// then you will find all documents, which contain a sub-document in @LIT{a}
/// that has an attribute @LIT{c} of value @LIT{1}. E.g., both documents
///
/// @LIT{{ a : { c : 1 }\, b : 1 }} and
///
/// @LIT{{ a : { c : 1\, b : 1 } }}
///
/// will match.
///
/// @FUN{@FA{collection}.byExample(@FA{path1}, @FA{value1}, ...)}
///
/// As alternative you can supply a list of paths and values.
///
/// @EXAMPLES
///
/// Use @FN{toArray} to get all documents at once:
///
/// @TINYEXAMPLE{simple18,convert into a list}
///
/// Use @FN{next} to loop over all documents:
///
/// @TINYEXAMPLE{simple19,iterate over the result-set}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.byExample = function () {
var example;
// example is given as only argument
if (arguments.length == 1) {
example = arguments[0];
}
// example is given as list
else {
example = {};
for (var i = 0; i < arguments.length; i += 2) {
example[arguments[i]] = arguments[i + 1];
}
}
// create a REAL array, otherwise JSON.stringify will fail
return new SimpleQueryByExample(this, example);
}
ArangoEdgesCollection.prototype.byExample = ArangoCollection.prototype.byExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- GENERAL ARRAY CURSOR
// -----------------------------------------------------------------------------
@ -837,6 +525,32 @@ function SimpleQueryAll (collection) {
SimpleQueryAll.prototype = new SimpleQuery();
SimpleQueryAll.prototype.constructor = SimpleQueryAll;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs an all query for a collection
///
/// @FUN{all()}
///
/// Selects all documents of a collection and returns a cursor. You can use
/// @FN{toArray}, @FN{next}, or @FN{hasNext} to access the result. The result
/// can be limited using the @FN{skip} and @FN{limit} operator.
///
/// @EXAMPLES
///
/// Use @FN{toArray} to get all documents at once:
///
/// @verbinclude simple3
///
/// Use @FN{next} to loop over all documents:
///
/// @verbinclude simple4
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.all = function () {
return new SimpleQueryAll(this);
}
ArangoEdgesCollection.prototype.all = ArangoCollection.prototype.all;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -991,7 +705,7 @@ SimpleQueryArray.prototype._PRINT = function () {
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief select query
/// @brief query-by-example
////////////////////////////////////////////////////////////////////////////////
function SimpleQueryByExample (collection, example) {
@ -1002,6 +716,85 @@ function SimpleQueryByExample (collection, example) {
SimpleQueryByExample.prototype = new SimpleQuery();
SimpleQueryByExample.prototype.constructor = SimpleQueryByExample;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
///
/// @FUN{@FA{collection}.byExample(@FA{example})}
///
/// Selects all documents of a collection that match the specified
/// example and returns a cursor.
///
/// You can use @FN{toArray}, @FN{next}, or @FN{hasNext} to access the
/// result. The result can be limited using the @FN{skip} and @FN{limit}
/// operator.
///
/// An attribute name of the form @LIT{a.b} is interpreted as attribute path,
/// not as attribute. If you use
///
/// @LIT{{ a : { c : 1 } }}
///
/// as example, then you will find all documents, such that the attribute
/// @LIT{a} contains a document of the form @LIT{{c : 1 }}. E.g., the document
///
/// @LIT{{ a : { c : 1 }\, b : 1 }}
///
/// will match, but the document
///
/// @LIT{{ a : { c : 1\, b : 1 } }}
///
/// will not.
///
/// However, if you use
///
/// @LIT{{ a.c : 1 }},
///
/// then you will find all documents, which contain a sub-document in @LIT{a}
/// that has an attribute @LIT{c} of value @LIT{1}. E.g., both documents
///
/// @LIT{{ a : { c : 1 }\, b : 1 }} and
///
/// @LIT{{ a : { c : 1\, b : 1 } }}
///
/// will match.
///
/// @FUN{@FA{collection}.byExample(@FA{path1}, @FA{value1}, ...)}
///
/// As alternative you can supply a list of paths and values.
///
/// @EXAMPLES
///
/// Use @FN{toArray} to get all documents at once:
///
/// @TINYEXAMPLE{simple18,convert into a list}
///
/// Use @FN{next} to loop over all documents:
///
/// @TINYEXAMPLE{simple19,iterate over the result-set}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.byExample = function () {
var example;
// example is given as only argument
if (arguments.length == 1) {
example = arguments[0];
}
// example is given as list
else {
example = {};
for (var i = 0; i < arguments.length; i += 2) {
example[arguments[i]] = arguments[i + 1];
}
}
// create a REAL array, otherwise JSON.stringify will fail
return new SimpleQueryByExample(this, example);
}
ArangoEdgesCollection.prototype.byExample = ArangoCollection.prototype.byExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -1053,6 +846,141 @@ SimpleQueryByExample.prototype._PRINT = function () {
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- RANGE QUERY
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief range query
////////////////////////////////////////////////////////////////////////////////
function SimpleQueryRange (collection, attribute, left, right, type) {
this._collection = collection;
this._attribute = attribute;
this._left = left;
this._right = right;
this._type = type;
}
SimpleQueryRange.prototype = new SimpleQuery();
SimpleQueryRange.prototype.constructor = SimpleQueryRange;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a range query for a collection
///
/// @FUN{@FA{collection}.range(@FA{attribute}, @FA{left}, @FA{right})}
///
/// Selects all documents of a collection such that the @FA{attribute} is
/// greater or equal than @FA{left} and strictly less than @FA{right}.
///
/// You can use @FN{toArray}, @FN{next}, or @FN{hasNext} to access the
/// result. The result can be limited using the @FN{skip} and @FN{limit}
/// operator.
///
/// An attribute name of the form @LIT{a.b} is interpreted as attribute path,
/// not as attribute.
///
/// @EXAMPLES
///
/// Use @FN{toArray} to get all documents at once:
///
/// @TINYEXAMPLE{simple-query-range-to-array,convert into a list}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.range = function (name, left, right) {
return new SimpleQueryRange(this, name, left, right, 0);
}
ArangoEdgesCollection.prototype.range = ArangoCollection.prototype.range;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a closed range query for a collection
///
/// @FUN{@FA{collection}.closedRange(@FA{attribute}, @FA{left}, @FA{right})}
///
/// Selects all documents of a collection such that the @FA{attribute} is
/// greater or equal than @FA{left} and less or equal than @FA{right}.
///
/// You can use @FN{toArray}, @FN{next}, or @FN{hasNext} to access the
/// result. The result can be limited using the @FN{skip} and @FN{limit}
/// operator.
///
/// An attribute name of the form @LIT{a.b} is interpreted as attribute path,
/// not as attribute.
///
/// @EXAMPLES
///
/// Use @FN{toArray} to get all documents at once:
///
/// @TINYEXAMPLE{simple-query-closed-range-to-array,convert into a list}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.closedRange = function (name, left, right) {
return new SimpleQueryRange(this, name, left, right, 1);
}
ArangoEdgesCollection.prototype.closedRange = ArangoCollection.prototype.closedRange;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief clones a range query
////////////////////////////////////////////////////////////////////////////////
SimpleQueryRange.prototype.clone = function () {
var query;
query = new SimpleQueryRange(this._collection, this._attribute, this._left, this._right, this._type);
query._skip = this._skip;
query._limit = this._limit;
return query;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief prints a range query
////////////////////////////////////////////////////////////////////////////////
SimpleQueryRange.prototype._PRINT = function () {
var text;
text = "SimpleQueryRange(" + this._collection.name() + ")";
if (this._skip != null && this._skip != 0) {
text += ".skip(" + this._skip + ")";
}
if (this._limit != null) {
text += ".limit(" + this._limit + ")";
}
internal.output(text);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- SIMPLE QUERY GEO
// -----------------------------------------------------------------------------
@ -1075,6 +1003,98 @@ function SimpleQueryGeo (collection, index) {
this._index = index;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a geo index selection
///
/// @FUN{@FA{collection}.geo(@FA{location})}
////////////////////////////////////////////
///
/// The next @FN{near} or @FN{within} operator will use the specific geo-spatial
/// index.
///
/// @FUN{@FA{collection}.geo(@FA{location}, @LIT{true})}
////////////////////////////////////////////////////////
///
/// The next @FN{near} or @FN{within} operator will use the specific geo-spatial
/// index.
///
/// @FUN{@FA{collection}.geo(@FA{latitude}, @FA{longitude})}
////////////////////////////////////////////////////////////
///
/// The next @FN{near} or @FN{within} operator will use the specific geo-spatial
/// index.
///
/// @EXAMPLES
///
/// Assume you have a location stored as list in the attribute @LIT{home}
/// and a destination stored in the attribute @LIT{work}. Than you can use the
/// @FN{geo} operator to select, which coordinates to use in a near query.
///
/// @TINYEXAMPLE{simple-query-geo,use a specific index}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.geo = function(loc, order) {
var idx;
var locateGeoIndex1 = function(collection, loc, order) {
var inds = collection.getIndexes();
for (var i = 0; i < inds.length; ++i) {
var index = inds[i];
if (index.type == "geo1") {
if (index.fields[0] == loc && index.geoJson == order) {
return index;
}
}
}
return null;
};
var locateGeoIndex2 = function(collection, lat, lon) {
var inds = collection.getIndexes();
for (var i = 0; i < inds.length; ++i) {
var index = inds[i];
if (index.type == "geo2") {
if (index.fields[0] == lat && index.fields[1] == lon) {
return index;
}
}
}
return null;
};
if (order === undefined) {
if (typeof loc === "object") {
idx = this.index(loc);
}
else {
idx = locateGeoIndex1(this, loc, false);
}
}
else if (typeof order === "boolean") {
idx = locateGeoIndex1(this, loc, order);
}
else {
idx = locateGeoIndex2(this, loc, order);
}
if (idx == null) {
var err = new ArangoError();
err.errorNum = internal.errors.ERROR_QUERY_GEO_INDEX_MISSING.code;
err.errorMessage = internal.errors.ERROR_QUERY_GEO_INDEX_MISSING.message;
throw err;
}
return new SimpleQueryGeo(this, idx.id);
}
ArangoEdgesCollection.prototype.geo = ArangoCollection.geo;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -1089,7 +1109,7 @@ function SimpleQueryGeo (collection, index) {
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief print a geo index
/// @brief prints a geo index
////////////////////////////////////////////////////////////////////////////////
SimpleQueryGeo.prototype._PRINT = function () {
@ -1191,6 +1211,65 @@ function SimpleQueryNear (collection, latitude, longitude, iid) {
SimpleQueryNear.prototype = new SimpleQuery();
SimpleQueryNear.prototype.constructor = SimpleQueryNear;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a near query for a collection
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude})}
/////////////////////////////////////////////////////////////
///
/// The default will find at most 100 documents near the coordinate
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted according to
/// the distance, with the nearest document coming first. If there are near
/// documents of equal distance, documents are chosen randomly from this set
/// until the limit is reached. It is possible to change the limit using the
/// @FA{limit} operator.
///
/// In order to use the @FN{near} operator, a geo index must be defined for the
/// collection. This index also defines which attribute holds the coordinates
/// for the document. If you have more then one geo-spatial index, you can use
/// the @FN{geo} operator to select a particular index.
///
/// @note @FN{near} does not support negative skips. However, you can still use
/// @FN{limit} followed to @FN{skip}.
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude}).limit(@FA{limit})}
///////////////////////////////////////////////////////////////////////////////
///
/// Limits the result to @FA{limit} documents instead of the default 100.
///
/// @note Unlike with multiple explicit limits, @FA{limit} will raise
/// the implicit default limit imposed by @FN{within}.
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude}).distance()}
////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @LIT{distance} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @FUN{@FA{collection}.near(@FA{latitude}, @FA{longitude}).distance(@FA{name})}
/////////////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @FA{name} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @EXAMPLES
///
/// To get the nearst two locations:
///
/// @TINYEXAMPLE{simple-query-near,nearest two location}
///
/// If you need the distance as well, then you can use the @FN{distance}
/// operator:
///
/// @TINYEXAMPLE{simple-query-near2,nearest two location with distance in meter}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.near = function (lat, lon) {
return new SimpleQueryNear(this, lat, lon);
}
ArangoEdgesCollection.prototype.near = ArangoCollection.prototype.near;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -1220,7 +1299,7 @@ SimpleQueryNear.prototype.clone = function () {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief print a near query
/// @brief prints a near query
////////////////////////////////////////////////////////////////////////////////
SimpleQueryNear.prototype._PRINT = function () {
@ -1338,6 +1417,45 @@ function SimpleQueryWithin (collection, latitude, longitude, radius, iid) {
SimpleQueryWithin.prototype = new SimpleQuery();
SimpleQueryWithin.prototype.constructor = SimpleQueryWithin;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a within query for a collection
///
/// @FUN{@FA{collection}.within(@FA{latitude}, @FA{longitude}, @FA{radius})}
////////////////////////////////////////////////////////////////////////////
///
/// This will find all documents with in a given radius around the coordinate
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted by distance.
///
/// In order to use the @FN{within} operator, a geo index must be defined for the
/// collection. This index also defines which attribute holds the coordinates
/// for the document. If you have more then one geo-spatial index, you can use
/// the @FN{geo} operator to select a particular index.
///
/// @FUN{@FA{collection}.within(@FA{latitude}, @FA{longitude}, @FA{radius})@LATEXBREAK.distance()}
//////////////////////////////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @LIT{_distance} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @FUN{@FA{collection}.within(@FA{latitude}, @FA{longitude}, @FA{radius})@LATEXBREAK.distance(@FA{name})}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// This will add an attribute @FA{name} to all documents returned, which
/// contains the distance between the given point and the document in meter.
///
/// @EXAMPLES
///
/// To find all documents within a radius of 2000 km use:
///
/// @TINYEXAMPLE{simple-query-within,within a radius}
////////////////////////////////////////////////////////////////////////////////
ArangoCollection.prototype.within = function (lat, lon, radius) {
return new SimpleQueryWithin(this, lat, lon, radius);
}
ArangoEdgesCollection.prototype.within = ArangoCollection.prototype.within;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
@ -1367,7 +1485,7 @@ SimpleQueryWithin.prototype.clone = function () {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief print a within query
/// @brief prints a within query
////////////////////////////////////////////////////////////////////////////////
SimpleQueryWithin.prototype._PRINT = function () {
@ -1445,6 +1563,7 @@ exports.GeneralArrayCursor = GeneralArrayCursor;
exports.SimpleQueryAll = SimpleQueryAll;
exports.SimpleQueryArray = SimpleQueryArray;
exports.SimpleQueryByExample = SimpleQueryByExample;
exports.SimpleQueryRange = SimpleQueryRange;
exports.SimpleQueryGeo = SimpleQueryGeo;
exports.SimpleQueryNear = SimpleQueryNear;
exports.SimpleQueryWithin = SimpleQueryWithin;

View File

@ -291,7 +291,7 @@ function SimpleQueryAllSkipLimitSuite () {
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: skip and limit with a collection
/// @brief test suite: query-by-example
////////////////////////////////////////////////////////////////////////////////
function SimpleQueryByExampleSuite () {
@ -392,6 +392,110 @@ function SimpleQueryByExampleSuite () {
};
}
// -----------------------------------------------------------------------------
// --SECTION-- basic tests for range
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: range
////////////////////////////////////////////////////////////////////////////////
function SimpleQueryRangeSuite () {
var cn = "UnitTestsCollectionRange";
var collection = null;
var age = function(d) { return d.age; };
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
internal.db._drop(cn);
collection = internal.db._create(cn, { waitForSync : false });
for (var i = 0; i < 100; ++i) {
collection.save({ age : i });
}
collection.ensureSkiplist("age");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
collection.drop();
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: range
////////////////////////////////////////////////////////////////////////////////
testRange : function () {
var l = collection.range("age", 10, 13).toArray().map(age).sort();
assertEqual([10,11,12], l);
l = collection.closedRange("age", 10, 13).toArray().map(age).sort();
assertEqual([10,11,12,13], l);
}
};
}
// -----------------------------------------------------------------------------
// --SECTION-- basic tests for unique range
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite: range
////////////////////////////////////////////////////////////////////////////////
function SimpleQueryUniqueRangeSuite () {
var cn = "UnitTestsCollectionRange";
var collection = null;
var age = function(d) { return d.age; };
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
internal.db._drop(cn);
collection = internal.db._create(cn, { waitForSync : false });
for (var i = 0; i < 100; ++i) {
collection.save({ age : i });
}
collection.ensureUniqueSkiplist("age");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
collection.drop();
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test: range
////////////////////////////////////////////////////////////////////////////////
testRange : function () {
var l = collection.range("age", 10, 13).toArray().map(age).sort();
assertEqual([10,11,12], l);
l = collection.closedRange("age", 10, 13).toArray().map(age).sort();
assertEqual([10,11,12,13], l);
}
};
}
// -----------------------------------------------------------------------------
// --SECTION-- main
// -----------------------------------------------------------------------------
@ -403,6 +507,8 @@ function SimpleQueryByExampleSuite () {
jsunity.run(SimpleQueryArraySkipLimitSuite);
jsunity.run(SimpleQueryAllSkipLimitSuite);
jsunity.run(SimpleQueryByExampleSuite);
jsunity.run(SimpleQueryRangeSuite);
jsunity.run(SimpleQueryUniqueRangeSuite);
return jsunity.done();

View File

@ -564,83 +564,6 @@ static string JS_server_server =
"/// @}\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// -----------------------------------------------------------------------------\n"
"// --SECTION-- skip-list helper\n"
"// -----------------------------------------------------------------------------\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @addtogroup V8Shell\n"
"/// @{\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief equal\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"EQ = ModuleCache[\"/internal\"].exports.EQ = function (value) {\n"
" return [ [ \"==\", value ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief less than\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"LT = ModuleCache[\"/internal\"].exports.LT = function (value) {\n"
" return [ [ \"<\", value ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief less than or equal\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"LE = ModuleCache[\"/internal\"].exports.LE = function (value) {\n"
" return [ [ \"<=\", value ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief greater than\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"GT = ModuleCache[\"/internal\"].exports.GT = function (value) {\n"
" return [ [ \">\", value ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief greater than or equal\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"GE = ModuleCache[\"/internal\"].exports.GE = function (value) {\n"
" return [ [ \">=\", value ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief range (left closed, right open)\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"RANGE = ModuleCache[\"/internal\"].exports.RANGE = function (left, right) {\n"
" return [ [ \">=\", left ], [ \"<\", right ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief open range\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"ORANGE = ModuleCache[\"/internal\"].exports.ORANGE = function (left, right) {\n"
" return [ [ \">\", left ], [ \"<\", right ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief closed range\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"CRANGE = ModuleCache[\"/internal\"].exports.CRANGE = function (left, right) {\n"
" return [ [ \">=\", left ], [ \"<=\", right ] ];\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @}\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// Local Variables:\n"
"// mode: outline-minor\n"
"// outline-regexp: \"^\\\\(/// @brief\\\\|/// @addtogroup\\\\|// --SECTION--\\\\|/// @page\\\\|/// @}\\\\)\"\n"

View File

@ -120,11 +120,11 @@ function ByExample (collection, example, skip, limit) {
idx = collection.lookupUniqueConstraint.apply(collection, attributes);
if (idx != null) {
console.info("found unique constraint %s", idx.id);
console.debug("found unique constraint %s", idx.id);
}
}
else {
console.info("found hash index %s", idx.id);
console.debug("found hash index %s", idx.id);
}
if (idx != null) {
@ -177,7 +177,7 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
///
/// Returns the a document of a collection that match the specified example or
/// @LIT{null}. The example must be specified as paths and values. See @ref
/// JSF_ArangoCollection_prototype_byExample for details.
/// @FN{byExample} for details.
///
/// @FUN{@FA{collection}.firstExample(@FA{path1}, @FA{value1}, ...)}
///
@ -221,6 +221,87 @@ ArangoEdgesCollection.prototype.firstExample = ArangoCollection.prototype.firstE
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- RANGED QUERY
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief ranged query
////////////////////////////////////////////////////////////////////////////////
function RangedQuery (collection, attribute, left, right, type, skip, limit) {
var idx = collection.lookupSkiplist(attribute);
if (idx == null) {
idx = collection.lookupUniqueSkiplist(attribute);
if (idx != null) {
console.debug("found unique skip-list index %s", idx.id);
}
}
else {
console.debug("found skip-list index %s", idx.id);
}
if (idx != null) {
var cond = {};
if (type == 0) {
cond[attribute] = [ [ ">=", left ], [ "<", right ] ];
}
else if (type == 1) {
cond[attribute] = [ [ ">=", left ], [ "<=", right ] ];
}
else {
throw "unknown type";
}
return collection.BY_CONDITION_SKIPLIST(idx.id, cond, skip, limit);
}
else {
throw "not implemented";
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes a query-by-example
////////////////////////////////////////////////////////////////////////////////
SQ.SimpleQueryRange.prototype.execute = function () {
var documents;
if (this._execution == null) {
if (this._skip == null || this._skip <= 0) {
this._skip = 0;
}
var documents = RangedQuery(this._collection,
this._attribute,
this._left,
this._right,
this._type,
this._skip,
this._limit);
this._execution = new SQ.GeneralArrayCursor(documents.documents);
this._countQuery = documents.count;
this._countTotal = documents.total;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- SIMPLE QUERY NEAR
// -----------------------------------------------------------------------------

View File

@ -563,83 +563,6 @@ ArangoCollection.prototype.toString = function(seen, path, names, level) {
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- skip-list helper
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup V8Shell
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief equal
////////////////////////////////////////////////////////////////////////////////
EQ = ModuleCache["/internal"].exports.EQ = function (value) {
return [ [ "==", value ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief less than
////////////////////////////////////////////////////////////////////////////////
LT = ModuleCache["/internal"].exports.LT = function (value) {
return [ [ "<", value ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief less than or equal
////////////////////////////////////////////////////////////////////////////////
LE = ModuleCache["/internal"].exports.LE = function (value) {
return [ [ "<=", value ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief greater than
////////////////////////////////////////////////////////////////////////////////
GT = ModuleCache["/internal"].exports.GT = function (value) {
return [ [ ">", value ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief greater than or equal
////////////////////////////////////////////////////////////////////////////////
GE = ModuleCache["/internal"].exports.GE = function (value) {
return [ [ ">=", value ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief range (left closed, right open)
////////////////////////////////////////////////////////////////////////////////
RANGE = ModuleCache["/internal"].exports.RANGE = function (left, right) {
return [ [ ">=", left ], [ "<", right ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief open range
////////////////////////////////////////////////////////////////////////////////
ORANGE = ModuleCache["/internal"].exports.ORANGE = function (left, right) {
return [ [ ">", left ], [ "<", right ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @brief closed range
////////////////////////////////////////////////////////////////////////////////
CRANGE = ModuleCache["/internal"].exports.CRANGE = function (left, right) {
return [ [ ">=", left ], [ "<=", right ] ];
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"