1
0
Fork 0
arangodb/js/actions/api-simple.js

2183 lines
72 KiB
JavaScript

/*jshint strict: false */
/*global CREATE_CURSOR */
////////////////////////////////////////////////////////////////////////////////
/// @brief simple queries
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB 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 ArangoDB GmbH, Cologne, Germany
///
/// @author Achim Brandt
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var actions = require("org/arangodb/actions");
var db = require("org/arangodb").db;
var ERRORS = require("internal").errors;
var API = "_api/simple/";
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief returns all documents of a collection matching a given example,
/// using a specific hash index
///
/// RESTHEADER{PUT /_api/simple/by-example-hash, Hash index}
///
/// **Note**: This is only used internally and should not be accessible by the user
/// and thus this documentation is private.
///
/// RESTBODYPARAM{query,string,required}
/// Contains the query specification.
///
/// RESTDESCRIPTION
///
/// This will find all documents matching a given example, using the specified
/// hash index.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *index*: The id of the index to be used for the query. The index must exist
/// and must be of type *hash*.
///
/// - *example*: an example document. The example must contain a value for each
/// attribute in the index.
///
/// - *skip*: The number of documents to skip in the query. (optional)
///
/// - *limit*: The maximal number of documents to return. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// RESTRETURNCODES
///
/// RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
/// The same error code is also returned if an invalid index id or type is used.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief returns all documents of a collection matching a given example,
/// using a specific skiplist index
///
/// @RESTHEADER{PUT /_api/simple/by-example-skiplist, Skiplist index}
///
/// **Note**: This is only used internally and should not be accesible by the user.
/// and thus this documentation is private.
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query specification.
///
/// @RESTDESCRIPTION
///
/// This will find all documents matching a given example, using the specified
/// skiplist index.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *index*: The id of the index to be used for the query. The index must
/// exist and must be of type *skiplist*.
///
/// - *example*: an example document. The example must contain a value for each
/// attribute in the index.
///
/// - *skip*: The number of documents to skip in the query. (optional)
///
/// - *limit*: The maximal number of documents to return. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
/// The same error code is also returned if an invalid index id or type is used.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief returns all documents of a collection matching a given condition,
/// using a specific skiplist index
///
/// @RESTHEADER{PUT /_api/simple/by-condition-skiplist,Query by-condition using Skiplist index}
///
/// **Note**: This is only used internally and should not be accesible by the user.
/// and thus this documentation is private.
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query specification.
///
/// @RESTDESCRIPTION
///
/// This will find all documents matching a given condition, using the specified
/// skiplist index.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *index*: The id of the index to be used for the query. The index must
/// exist and must be of type *skiplist*.
///
/// - *condition*: the condition which all returned documents shall satisfy.
/// Conditions must be specified for all indexed attributes.
///
/// - *skip*: The number of documents to skip in the query. (optional)
///
/// - *limit*: The maximal number of documents to return. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
/// The same error code is also returned if an invalid index id or type is used.
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief create a cursor response
////////////////////////////////////////////////////////////////////////////////
function createCursorResponse (req, res, cursor) {
actions.resultCursor(req, res, cursor, undefined, { countRequested: true });
}
////////////////////////////////////////////////////////////////////////////////
/// @brief setup an index query
////////////////////////////////////////////////////////////////////////////////
function setupIndexQuery (name, func, isExampleQuery) {
actions.defineHttp({
url: API + name,
callback: function (req, res) {
try {
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 || 0;
var name = body.collection;
var index = body.index;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
return;
}
var result;
if (isExampleQuery) {
if (typeof body.example !== "object" || Array.isArray(body.example)) {
actions.badParameter(req, res, "example");
return;
}
result = collection[func](index, body.example);
}
else {
if (typeof body.condition !== "object" || Array.isArray(body.condition)) {
actions.badParameter(req, res, "condition");
return;
}
result = collection[func](index, body.condition);
}
if (skip > 0) {
result.skip(skip);
}
if (limit !== undefined && limit !== null) {
result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), body.batchSize, body.ttl));
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register all these functions
////////////////////////////////////////////////////////////////////////////////
function setupIndexQueries () {
var map = {
"by-example-hash" : [ "byExampleHash", true ],
"by-example-skiplist" : [ "byExampleSkiplist", true ],
"by-condition-skiplist" : [ "byConditionSkiplist", false ]
};
var m;
for (m in map) {
if (map.hasOwnProperty(m)) {
setupIndexQuery(m, map[m][0], map[m][1]);
}
}
}
setupIndexQueries();
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_any
/// @brief returns a random document from a collection
///
/// @RESTHEADER{PUT /_api/simple/any, Return a random document}
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// Returns a random document from a collection. The call expects a JSON object
/// as body with the following attributes:
///
/// - *collection*: The identifier or name of the collection to query.
///
/// Returns a JSON object with the document stored in the attribute
/// *document* if the collection contains at least one document. If
/// the collection is empty, the *document* attrbute contains null.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleAny}
/// var cn = "products";
/// db._drop(cn);
/// var collection = db._create(cn);
/// collection.save({"Hello1" : "World1" });
/// collection.save({"Hello2" : "World2" });
/// collection.save({"Hello3" : "World3" });
/// collection.save({"Hello4" : "World4" });
/// collection.save({"Hello5" : "World5" });
///
/// var url = "/_api/simple/any";
/// var body = '{ "collection": "products" }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "any",
callback: function (req, res) {
try {
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (req.requestType !== actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var name = body.collection;
var id = parseInt(name, 10) || name;
var collection = db._collection(id);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else {
var result = { document: collection.any() };
actions.resultOk(req, res, actions.HTTP_OK, result);
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_near
/// @brief returns all documents of a collection near a given location
///
/// @RESTHEADER{PUT /_api/simple/near, Returns documents near a coordinate}
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// The default will find at most 100 documents near the given coordinate. The
/// returned array is sorted according to the distance, with the nearest document
/// being first in the return array. If there are near documents of equal distance, documents
/// are chosen randomly from this set until the limit is reached.
///
/// In order to use the *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 than one geo-spatial index, you can use
/// the *geo* field to select a particular index.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *latitude*: The latitude of the coordinate.
///
/// - *longitude*: The longitude of the coordinate.
///
/// - *distance*: If given, the attribute key used to return the distance to
/// the given coordinate. (optional). If specified, distances are returned in meters.
///
/// - *skip*: The number of documents to skip in the query. (optional)
///
/// - *limit*: The maximal amount of documents to return. The *skip* is
/// applied before the *limit* restriction. The default is 100. (optional)
///
/// - *geo*: If given, the identifier of the geo-index to use. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// Note: the *near* simple query is **deprecated** as of ArangoDB 2.6.
/// This API may be removed in future versions of ArangoDB. The preferred
/// way for retrieving documents from a collection using the near operator is
/// to issue an [AQL query](../Aql/GeoFunctions.md) using the *NEAR* function as follows:
///
/// FOR doc IN NEAR(@@collection, @latitude, @longitude, @limit)
/// RETURN doc`
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// Without distance:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleNear}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// var loc = products.ensureGeoIndex("loc");
/// var i;
/// for (i = -0.01; i <= 0.01; i += 0.002) {
/// products.save({ name : "Name/" + i + "/",loc: [ i, 0 ] });
/// }
/// var url = "/_api/simple/near";
/// var body = '{ ' +
/// '"collection": "products", ' +
/// '"latitude" : 0, ' +
/// '"longitude" : 0, ' +
/// '"skip" : 1, ' +
/// '"limit" : 2 ' +
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// With distance:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleNearDistance}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// var loc = products.ensureGeoIndex("loc");
/// var i;
/// for (i = -0.01; i <= 0.01; i += 0.002) {
/// products.save({ name : "Name/" + i + "/",loc: [ i, 0 ] });
/// }
/// var url = "/_api/simple/near";
/// var body = '{ ' +
/// '"collection": "products", ' +
/// '"latitude" : 0, ' +
/// '"longitude" : 0, ' +
/// '"skip" : 1, ' +
/// '"limit" : 3, ' +
/// '"distance" : "distance" ' +
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "near",
callback : function (req, res) {
try {
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 latitude = body.latitude;
var longitude = body.longitude;
var distance = body.distance;
var name = body.collection;
var geo = body.geo;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (latitude === null || latitude === undefined) {
actions.badParameter(req, res, "latitude");
}
else if (longitude === null || longitude === undefined) {
actions.badParameter(req, res, "longitude");
}
else {
var result;
if (geo === null || geo === undefined) {
result = collection.near(latitude, longitude);
}
else {
result = collection.geo({ id : geo }).near(latitude, longitude);
}
if (skip !== null && skip !== undefined) {
result = result.skip(skip);
}
if (limit !== null && limit !== undefined) {
result = result.limit(limit);
}
if (distance !== null && distance !== undefined) {
result = result.distance(distance);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), body.batchSize, body.ttl));
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_within
/// @brief returns all documents of a collection within a given radius
///
/// @RESTHEADER{PUT /_api/simple/within, Find documents within a radius around a coordinate}
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents within a given radius around the coordinate
/// (*latitude*, *longitude*). The returned list is sorted by distance.
///
/// In order to use the *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 than one geo-spatial index,
/// you can use the *geo* field to select a particular index.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *latitude*: The latitude of the coordinate.
///
/// - *longitude*: The longitude of the coordinate.
///
/// - *radius*: The maximal radius (in meters).
///
/// - *distance*: If given, the attribute key used to return the distance to
/// the given coordinate. (optional). If specified, distances are returned in meters.
///
/// - *skip*: The number of documents to skip in the query. (optional)
///
/// - *limit*: The maximal amount of documents to return. The *skip* is
/// applied before the *limit* restriction. The default is 100. (optional)
///
/// - *geo*: If given, the identifier of the geo-index to use. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// Note: the *within* simple query is **deprecated** as of ArangoDB 2.6.
/// This API may be removed in future versions of ArangoDB. The preferred
/// way for retrieving documents from a collection using the near operator is
/// to issue an [AQL query](../Aql/GeoFunctions.md) using the *WITHIN* function as follows:
///
/// FOR doc IN WITHIN(@@collection, @latitude, @longitude, @radius, @distanceAttributeName)
/// RETURN doc
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// Without distance:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleWithin}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// var loc = products.ensureGeoIndex("loc");
/// var i;
/// for (i = -0.01; i <= 0.01; i += 0.002) {
/// products.save({ name : "Name/" + i + "/",loc: [ i, 0 ] });
/// }
/// var url = "/_api/simple/near";
/// var body = '{ ' +
/// '"collection": "products", ' +
/// '"latitude" : 0, ' +
/// '"longitude" : 0, ' +
/// '"skip" : 1, ' +
/// '"limit" : 2, ' +
/// '"radius" : 500 ' +
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// With distance:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleWithinDistance}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// var loc = products.ensureGeoIndex("loc");
/// var i;
/// for (i = -0.01; i <= 0.01; i += 0.002) {
/// products.save({ name : "Name/" + i + "/",loc: [ i, 0 ] });
/// }
/// var url = "/_api/simple/near";
/// var body = '{ "collection": "products", "latitude" : 0, "longitude" : 0, ' +
/// '"skip" : 1, "limit" : 3, "distance" : "distance", "radius" : 300 }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "within",
callback : function (req, res) {
try {
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 latitude = body.latitude;
var longitude = body.longitude;
var distance = body.distance;
var radius = body.radius;
var geo = body.geo;
var name = body.collection;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (latitude === null || latitude === undefined) {
actions.badParameter(req, res, "latitude");
}
else if (longitude === null || longitude === undefined) {
actions.badParameter(req, res, "longitude");
}
else {
var result;
if (geo === null || geo === undefined) {
result = collection.within(latitude, longitude, radius);
}
else {
result = collection.geo({ id : geo }).within(latitude, longitude, radius);
}
if (skip !== null && skip !== undefined) {
result = result.skip(skip);
}
if (limit !== null && limit !== undefined) {
result = result.limit(limit);
}
if (distance !== null && distance !== undefined) {
result = result.distance(distance);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), body.batchSize, body.ttl));
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_within_rectangle
/// @brief returns all documents of a collection within a rectangle
///
/// @RESTHEADER{PUT /_api/simple/within-rectangle, Within rectangle query}
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents within the specified rectangle (determined by
/// the given coordinates (*latitude1*, *longitude1*, *latitude2*, *longitude2*).
///
/// In order to use the *within-rectangle* query, 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 than one geo-spatial index,
/// you can use the *geo* field to select a particular index.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *latitude1*: The latitude of the first rectangle coordinate.
///
/// - *longitude1*: The longitude of the first rectangle coordinate.
///
/// - *latitude2*: The latitude of the second rectangle coordinate.
///
/// - *longitude2*: The longitude of the second rectangle coordinate.
///
/// - *skip*: The number of documents to skip in the query. (optional)
///
/// - *limit*: The maximal amount of documents to return. The *skip* is
/// applied before the *limit* restriction. The default is 100. (optional)
///
/// - *geo*: If given, the identifier of the geo-index to use. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleWithinRectangle}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// var loc = products.ensureGeoIndex("loc");
/// var i;
/// for (i = -0.01; i <= 0.01; i += 0.002) {
/// products.save({ name : "Name/" + i + "/",loc: [ i, 0 ] });
/// }
/// var url = "/_api/simple/within-rectangle";
/// var body = {
/// collection: "products",
/// latitude1 : 0,
/// longitude1 : 0,
/// latitude2 : 0.2,
/// longitude2 : 0.2,
/// skip : 1,
/// limit : 2
/// };
///
/// var response = logCurlRequest('PUT', url, JSON.stringify(body));
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "within-rectangle",
callback : function (req, res) {
try {
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 latitude1 = body.latitude1;
var longitude1 = body.longitude1;
var latitude2 = body.latitude2;
var longitude2 = body.longitude2;
var geo = body.geo;
var name = body.collection;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (latitude1 === null || latitude1 === undefined) {
actions.badParameter(req, res, "latitude1");
}
else if (longitude1 === null || longitude1 === undefined) {
actions.badParameter(req, res, "longitude1");
}
else if (latitude2 === null || latitude2 === undefined) {
actions.badParameter(req, res, "latitude2");
}
else if (longitude2 === null || longitude2 === undefined) {
actions.badParameter(req, res, "longitude2");
}
else {
var result;
if (geo === null || geo === undefined) {
result = collection.withinRectangle(latitude1, longitude1, latitude2, longitude2);
}
else {
result = collection.geo({ id : geo }).withinRectangle(latitude1, longitude1, latitude2, longitude2);
}
if (skip !== null && skip !== undefined) {
result = result.skip(skip);
}
if (limit !== null && limit !== undefined) {
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), body.batchSize, body.ttl));
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_fulltext
/// @brief returns documents of a collection as a result of a fulltext query
///
/// @RESTHEADER{PUT /_api/simple/fulltext, Fulltext index query}
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents from the collection that match the fulltext
/// query specified in *query*.
///
/// In order to use the *fulltext* operator, a fulltext index must be defined
/// for the collection and the specified attribute.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *attribute*: The attribute that contains the texts.
///
/// - *query*: The fulltext query. Please refer to [Fulltext queries](../SimpleQueries/FulltextQueries.html)
/// for details.
///
/// - *skip*: The number of documents to skip in the query (optional).
///
/// - *limit*: The maximal amount of documents to return. The *skip*
/// is applied before the *limit* restriction. (optional)
///
/// - *index*: The identifier of the fulltext-index to use.
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// Note: the *fulltext* simple query is **deprecated** as of ArangoDB 2.6.
/// This API may be removed in future versions of ArangoDB. The preferred
/// way for retrieving documents from a collection using the near operator is
/// to issue an AQL query using the *FULLTEXT* [AQL function](../Aql/FulltextFunctions.md)
/// as follows:
///
/// FOR doc IN FULLTEXT(@@collection, @attributeName, @queryString, @limit)
/// RETURN doc
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleFulltext}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({"text" : "this text contains word" });
/// products.save({"text" : "this text also has a word" });
/// products.save({"text" : "this is nothing" });
/// var loc = products.ensureFulltextIndex("text");
/// var url = "/_api/simple/fulltext";
/// var body = '{ "collection": "products", "attribute" : "text", "query" : "word" }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "fulltext",
callback : function (req, res) {
try {
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 attribute = body.attribute;
var query = body.query;
var iid = body.index || undefined;
var name = body.collection;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (attribute === null || attribute === undefined) {
actions.badParameter(req, res, "attribute");
}
else if (query === null || query === undefined) {
actions.badParameter(req, res, "query");
}
else {
var result = collection.fulltext(attribute, query, iid);
if (skip !== null && skip !== undefined) {
result = result.skip(skip);
}
if (limit !== null && limit !== undefined) {
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), body.batchSize, body.ttl));
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_by_example
/// @brief returns all documents of a collection matching a given example
///
/// @RESTHEADER{PUT /_api/simple/by-example, Simple query by-example}
///
/// @RESTBODYPARAM{query,string,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents matching a given example.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *example*: The example document.
///
/// - *skip*: The number of documents to skip in the query (optional).
///
/// - *limit*: The maximal amount of documents to return. The *skip*
/// is applied before the *limit* restriction. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// Matching an attribute:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleByExample}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/by-example";
/// var body = '{ "collection": "products", "example" : { "i" : 1 } }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// Matching an attribute which is a sub-document:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleByExample2}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/by-example";
/// var body = '{ "collection": "products", "example" : { "a.j" : 1 } }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// Matching an attribute within a sub-document:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleByExample3}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/by-example";
/// var body = '{ "collection": "products", "example" : { "a" : { "j" : 1 } } }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "by-example",
callback : function (req, res) {
try {
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 example = body.example;
var name = body.collection;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (typeof example !== "object") {
actions.badParameter(req, res, "example");
}
else {
var result = collection.byExample(example);
if (skip !== null && skip !== undefined) {
result = result.skip(skip);
}
if (limit !== null && limit !== undefined) {
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), body.batchSize, body.ttl));
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_first_example
/// @brief returns one document of a collection matching a given example
///
/// @RESTHEADER{PUT /_api/simple/first-example, Find documents matching an example}
///
/// @RESTBODYPARAM{query,json,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will return the first document matching a given example.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *example*: The example document.
///
/// Returns a result containing the document or *HTTP 404* if no
/// document matched the example.
///
/// If more than one document in the collection matches the specified example, only
/// one of these documents will be returned, and it is undefined which of the matching
/// documents is returned.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned when the query was successfully executed.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// If a matching document was found:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleFirstExample}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/first-example";
/// var body = '{ "collection": "products", "example" : { "i" : 1 } }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// If no document was found:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleFirstExampleNotFound}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/first-example";
/// var body = '{ "collection": "products", "example" : { "l" : 1 } }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 404);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "first-example",
callback : function (req, res) {
try {
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (req.requestType !== actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var example = body.example;
var name = body.collection;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (typeof example !== "object") {
actions.badParameter(req, res, "example");
}
else {
var result = collection.byExample(example).limit(1);
if (result.hasNext()) {
actions.resultOk(req, res, actions.HTTP_OK, { document : result.next() });
}
else {
actions.resultNotFound(req, res, ERRORS.ERROR_HTTP_NOT_FOUND.code, "no match");
}
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_first
/// @brief returns the first document(s) of a collection
///
/// @RESTHEADER{PUT /_api/simple/first, First document of a collection}
///
/// @RESTBODYPARAM{query,json,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will return the first document(s) from the collection, in the order of
/// insertion/update time. When the *count* argument is supplied, the result
/// will be an array of documents, with the "oldest" document being first in the
/// result array.
/// If the *count* argument is not supplied, the result is the "oldest" document
/// of the collection, or *null* if the collection is empty.
///
/// The request body must be a JSON object with the following attributes:
/// - *collection*: the name of the collection
///
/// - *count*: the number of documents to return at most. Specifying count is
/// optional. If it is not specified, it defaults to 1.
///
/// Note: this method is not supported for sharded collections with more than
/// one shard.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned when the query was successfully executed.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// Retrieving the first n documents:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleFirst}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/first";
/// var body = '{ "collection": "products", "count" : 2 }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// Retrieving the first document:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleFirstSingle}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/first";
/// var body = '{ "collection": "products" }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "first",
callback : function (req, res) {
try {
if (req.requestType !== actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var body = actions.getJsonBody(req, res);
var name = body.collection;
var count = body.count;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
if (count) {
actions.resultOk(req, res, actions.HTTP_OK, { result : collection.first(count) });
}
else {
actions.resultOk(req, res, actions.HTTP_OK, { result : collection.first() });
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_last
/// @brief returns the last document(s) of a collection
///
/// @RESTHEADER{PUT /_api/simple/last, Last document of a collection}
///
/// @RESTBODYPARAM{query,json,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will return the last documents from the collection, in the order of
/// insertion/update time. When the *count* argument is supplied, the result
/// will be an array of documents, with the "latest" document being first in the
/// result array.
///
/// The request body must be a JSON object with the following attributes:
/// - *collection*: the name of the collection
///
/// - *count*: the number of documents to return at most. Specifying count is
/// optional. If it is not specified, it defaults to 1.
///
/// If the *count* argument is not supplied, the result is the "latest" document
/// of the collection, or *null* if the collection is empty.
///
/// Note: this method is not supported for sharded collections with more than
/// one shard.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned when the query was successfully executed.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// Retrieving the last n documents:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleLast}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/last";
/// var body = '{ "collection": "products", "count" : 2 }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
///
/// Retrieving the first document:
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleLastSingle}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/last";
/// var body = '{ "collection": "products" }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "last",
callback : function (req, res) {
try {
if (req.requestType !== actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var body = actions.getJsonBody(req, res);
var name = body.collection;
var count = body.count;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
if (count) {
actions.resultOk(req, res, actions.HTTP_OK, { result : collection.last(count) });
}
else {
actions.resultOk(req, res, actions.HTTP_OK, { result : collection.last() });
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_range
/// @brief returns all documents of a collection within a range
///
/// @RESTHEADER{PUT /_api/simple/range, Simple range query}
///
/// @RESTBODYPARAM{query,json,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents within a given range. In order to execute a
/// range query, a skip-list index on the queried attribute must be present.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to query.
///
/// - *attribute*: The attribute path to check.
///
/// - *left*: The lower bound.
///
/// - *right*: The upper bound.
///
/// - *closed*: If *true*, use interval including *left* and *right*,
/// otherwise exclude *right*, but include *left*.
///
/// - *skip*: The number of documents to skip in the query (optional).
///
/// - *limit*: The maximal amount of documents to return. The *skip*
/// is applied before the *limit* restriction. (optional)
///
/// Returns a cursor containing the result, see [Http Cursor](../HttpAqlQueryCursor/README.md) for details.
///
/// Note: the *range* simple query is **deprecated** as of ArangoDB 2.6.
/// The function may be removed in future versions of ArangoDB. The preferred
/// way for retrieving documents from a collection within a specific range
/// is to use an AQL query as follows:
///
/// FOR doc IN @@collection
/// FILTER doc.value >= @left && doc.value < @right
/// LIMIT @skip, @limit
/// RETURN doc`
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{201}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown or no
/// suitable index for the range query is present. The response body contains
/// an error document in this case.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleRange}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.ensureUniqueSkiplist("i");
/// products.save({ "i": 1});
/// products.save({ "i": 2});
/// products.save({ "i": 3});
/// products.save({ "i": 4});
/// var url = "/_api/simple/range";
/// var body = '{ "collection": "products", "attribute" : "i", "left" : 2, "right" : 4 }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 201);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "range",
callback : function (req, res) {
try {
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 collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else {
var result;
if (closed) {
result = collection.closedRange(attribute, left, right);
}
else {
result = collection.range(attribute, left, right);
}
if (skip !== null && skip !== undefined) {
result = result.skip(skip);
}
if (limit !== null && limit !== undefined) {
result = result.limit(limit);
}
createCursorResponse(req, res, CREATE_CURSOR(result.toArray(), body.batchSize, body.ttl));
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_remove_by_example
/// @brief removes all documents of a collection that match an example
///
/// @RESTHEADER{PUT /_api/simple/remove-by-example, Remove documents by example}
///
/// @RESTBODYPARAM{query,json,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents in the collection that match the specified
/// example object.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to remove from.
///
/// - *example*: An example document that all collection documents are compared
/// against.
///
/// - options: a json object which can contains following attributes:
///
/// - *waitForSync*: if set to true, then all removal operations will
/// instantly be synchronized to disk. If this is not specified, then the
/// collection's default sync behavior will be applied.
///
/// - *limit*: an optional value that determines how many documents to
/// delete at most. If *limit* is specified but is less than the number
/// of documents in the collection, it is undefined which of the documents
/// will be deleted.
///
/// Note: the *limit* attribute is not supported on sharded collections.
/// Using it will result in an error.
///
/// Returns the number of documents that were deleted.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleRemoveByExample}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/remove-by-example";
/// var body = '{ "collection": "products", "example" : { "a" : { "j" : 1 } } }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// Using Parameter: waitForSync and limit
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleRemoveByExample_1}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/remove-by-example";
/// var body = '{ "collection": "products", "example" : { "a" : { "j" : 1 } },' +
/// '"waitForSync": true, "limit": 2 }';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// Using Parameter: waitForSync and limit with new signature
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleRemoveByExample_2}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/remove-by-example";
/// var body = '{'+
/// '"collection": "products",' +
/// '"example" : { "a" : { "j" : 1 } },' +
/// '"options": {"waitForSync": true, "limit": 2} ' +
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "remove-by-example",
callback : function (req, res) {
try {
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (req.requestType !== actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var example = body.example;
var name = body.collection;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (typeof example !== "object" || Array.isArray(example)) {
actions.badParameter(req, res, "example");
}
else {
var options = body.options;
if (typeof options === "undefined") {
var waitForSync = body.waitForSync || undefined;
var limit = body.limit || null;
options = {waitForSync: waitForSync, limit: limit};
}
var result = collection.removeByExample(example, options);
actions.resultOk(req, res, actions.HTTP_OK, { deleted: result });
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_replace_by_example
/// @brief replaces the body of all documents of a collection that match an
/// example
///
/// @RESTHEADER{PUT /_api/simple/replace-by-example, Replace documents by example}
///
/// @RESTBODYPARAM{query,json,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents in the collection that match the specified
/// example object, and replace the entire document body with the new value
/// specified. Note that document meta-attributes such as *_id*, *_key*,
/// *_from*, *_to* etc. cannot be replaced.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to replace within.
///
/// - *example*: An example document that all collection documents are compared
/// against.
///
/// - *newValue*: The replacement document that will get inserted in place
/// of the "old" documents.
///
/// - *options*: a json object which can contain following attributes
///
/// - *waitForSync*: if set to true, then all removal operations will
/// instantly be synchronized to disk. If this is not specified, then the
/// collection's default sync behavior will be applied.
///
/// - *limit*: an optional value that determines how many documents to
/// replace at most. If *limit* is specified but is less than the number
/// of documents in the collection, it is undefined which of the documents
/// will be replaced.
///
/// Note: the *limit* attribute is not supported on sharded collections.
/// Using it will result in an error.
///
/// Returns the number of documents that were replaced.
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned if the query was executed successfully.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
///
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleReplaceByExample}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/replace-by-example";
/// var body = '{ ' +
/// '"collection": "products", ' +
/// '"example" : { "a" : { "j" : 1 } }, ' +
/// '"newValue" : {"foo" : "bar"}, ' +
/// '"limit" : 3 ' +
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// Using new Signature for attributes WaitForSync and limit
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleReplaceByExampleWaitForSync}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/replace-by-example";
/// var body = '{ ' +
/// '"collection": "products", ' +
/// '"example" : { "a" : { "j" : 1 } }, ' +
/// '"newValue" : {"foo" : "bar"}, ' +
/// '"options": {"limit" : 3, "waitForSync": true }'+
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "replace-by-example",
callback : function (req, res) {
try {
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (req.requestType !== actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var example = body.example;
var newValue = body.newValue;
var name = body.collection;
var collection = db._collection(name);
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (typeof example !== "object" || Array.isArray(example)) {
actions.badParameter(req, res, "example");
}
else if (typeof newValue !== "object" || Array.isArray(newValue)) {
actions.badParameter(req, res, "newValue");
}
else {
var options = body.options;
if (typeof options === "undefined") {
var waitForSync = body.waitForSync || undefined;
var limit = body.limit || null;
options = {waitForSync: waitForSync, limit: limit};
}
var result = collection.replaceByExample(example, newValue, options);
actions.resultOk(req, res, actions.HTTP_OK, { replaced: result });
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSA_put_api_simple_update_by_example
/// @brief partially updates the body of all documents of a collection that
/// match an example
///
/// @RESTHEADER{PUT /_api/simple/update-by-example, Update documents by example}
///
/// @RESTBODYPARAM{query,json,required}
/// Contains the query.
///
/// @RESTDESCRIPTION
///
/// This will find all documents in the collection that match the specified
/// example object, and partially update the document body with the new value
/// specified. Note that document meta-attributes such as *_id*, *_key*,
/// *_from*, *_to* etc. cannot be replaced.
///
/// The call expects a JSON object as body with the following attributes:
///
/// - *collection*: The name of the collection to update within.
///
/// - *example*: An example document that all collection documents are compared
/// against.
///
/// - *newValue*: A document containing all the attributes to update in the
/// found documents.
///
/// - *options*: a json object which can contains following attributes:
///
/// - *keepNull*: This parameter can be used to modify the behavior when
/// handling *null* values. Normally, *null* values are stored in the
/// database. By setting the *keepNull* parameter to *false*, this
/// behavior can be changed so that all attributes in *data* with *null*
/// values will be removed from the updated document.
///
/// - *waitForSync*: if set to true, then all removal operations will
/// instantly be synchronized to disk. If this is not specified, then the
/// collection's default sync behavior will be applied.
///
/// - *limit*: an optional value that determines how many documents to
/// update at most. If *limit* is specified but is less than the number
/// of documents in the collection, it is undefined which of the documents
/// will be updated.
///
/// Note: the *limit* attribute is not supported on sharded collections.
/// Using it will result in an error.
///
/// Returns the number of documents that were updated.
///
///
/// @RESTRETURNCODES
///
/// @RESTRETURNCODE{200}
/// is returned if the collection was updated successfully and *waitForSync* was
/// *true*.
///
/// @RESTRETURNCODE{400}
/// is returned if the body does not contain a valid JSON representation of a
/// query. The response body contains an error document in this case.
///
/// @RESTRETURNCODE{404}
/// is returned if the collection specified by *collection* is unknown. The
/// response body contains an error document in this case.
///
/// @EXAMPLES
/// using old syntax for options
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleUpdateByExample}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/update-by-example";
/// var body = '{ ' +
/// '"collection": "products", ' +
/// '"example" : { "a" : { "j" : 1 } }, ' +
/// '"newValue" : { "a" : { "j" : 22 } }, ' +
/// '"limit" : 3 ' +
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// using new signature for options
/// @EXAMPLE_ARANGOSH_RUN{RestSimpleUpdateByExample_1}
/// var cn = "products";
/// db._drop(cn);
/// var products = db._create(cn);
/// products.save({ "a": { "k": 1, "j": 1 }, "i": 1});
/// products.save({ "a": { "j": 1 }, "i": 1});
/// products.save({ "i": 1});
/// products.save({ "a": { "k": 2, "j": 2 }, "i": 1});
/// var url = "/_api/simple/update-by-example";
/// var body = '{ ' +
/// '"collection": "products", ' +
/// '"example" : { "a" : { "j" : 1 } }, ' +
/// '"newValue" : { "a" : { "j" : 22 } }, ' +
/// '"options" : { "limit" : 3, "waitForSync": true } ' +
/// '}';
///
/// var response = logCurlRequest('PUT', url, body);
///
/// assert(response.code === 200);
///
/// logJsonResponse(response);
/// db._drop(cn);
/// @END_EXAMPLE_ARANGOSH_RUN
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: API + "update-by-example",
callback : function (req, res) {
try {
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (req.requestType !== actions.PUT) {
actions.resultUnsupported(req, res);
}
else {
var example = body.example;
var newValue = body.newValue;
var name = body.collection;
var collection = db._collection(name);
var limit = body.limit || null;
var keepNull = body.keepNull || null;
if (collection === null) {
actions.collectionNotFound(req, res, name);
}
else if (typeof example !== "object" || Array.isArray(example)) {
actions.badParameter(req, res, "example");
}
else if (typeof newValue !== "object" || Array.isArray(newValue)) {
actions.badParameter(req, res, "newValue");
}
else {
var options = body.options;
if (typeof options === "undefined") {
var waitForSync = body.waitForSync || undefined;
limit = body.limit || undefined;
options = {waitForSync: waitForSync, keepNull: keepNull, limit: limit};
}
var result = collection.updateByExample(example,
newValue,
options);
actions.resultOk(req, res, actions.HTTP_OK, { updated: result });
}
}
}
catch (err) {
actions.resultException(req, res, err, undefined, false);
}
}
});
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End: