1
0
Fork 0

fixed byExample and firstExample

This commit is contained in:
Frank Celler 2012-05-07 16:08:23 +02:00
parent 883760f865
commit 5c5f0827b3
13 changed files with 292 additions and 72 deletions

View File

@ -0,0 +1,18 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/by-example
{ "collection" : "3179705695", "example" : [ { "i" : 1 } ] }
HTTP/1.1 201 Created
content-type: application/json
{
"result": [
{ "a": { "k": 2, "j": 2 }, "i": 1, "_rev": 3181802847, "_id": "3179705695/3181802847" },
{ "a": { "j": 1 }, "i": 1, "_rev": 3181475167, "_id": "3179705695/3181475167" },
{ "a": { "k": 1, "j": 1 }, "i": 1, "_rev": 3181737311, "_id": "3179705695/3181737311" },
{ "i": 1, "_rev": 3181147487, "_id": "3179705695/3181147487" }
],
"count": 4,
"error": false,
"hasMore": false,
"code": 201
}

View File

@ -0,0 +1,15 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/by-example
{ "collection" : "3179705695", "example" : [ { "a" : { "j" : 1 } } ] }
HTTP/1.1 201 Created
content-type: application/json
{
"result": [
{ "a": { "j": 1 }, "i": 1, "_rev": 3181475167, "_id": "3179705695/3181475167" }
],
"count": 1,
"error": false,
"hasMore": false,
"code": 201
}

View File

@ -0,0 +1,16 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/by-example
{ "collection" : "3179705695", "example" : [ "a.j", 1 ] }
HTTP/1.1 201 Created
content-type: application/json
{
"result": [
{ "a": { "j": 1 }, "i": 1, "_rev": 3181475167, "_id": "3179705695/3181475167" },
{ "a": { "k": 1, "j": 1 }, "i": 1, "_rev": 3181737311, "_id": "3179705695/3181737311" }
],
"count": 2,
"error": false,
"hasMore": false,
"code": 201
}

View File

@ -0,0 +1,11 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/first-example
{ "collection" : "666351134", "example" : [ "a.j", 1, "a.k", 1 ] }
HTTP/1.1 200 OK
content-type: application/json
{
"error": false,
"code": 200,
"document": { "_rev": 668382750, "_id": "666351134/668382750", "a": { "k": 1, "j": 1, "l" : 10 }, "i": 1 }
}

View File

@ -0,0 +1,12 @@
> curl --data @- -X PUT --dump - http://localhost:8529/_api/simple/first-example
{ "collection" : "666351134", "example" : [ "a.j", 1, "a.k", 2 ] }
HTTP/1.1 404 Not Found
content-type: application/json
{
"errorMessage": "no match",
"error": true,
"code": 404,
"errorNum": 404
}

View File

@ -11,6 +11,6 @@ MANUAL_DST="fceller@www.avocadodb.org:/srv/www/www.avocadodb.org/avoc/manuals"
publish:
(cd Doxygen/wiki && git checkout --force && git pull)
$(MAKE) wiki
(cd Doxygen/wiki && git commit -m "`date`" -a; git push)
(cd Doxygen/wiki && git add *.md; git commit -m "`date`" -a; git push)
@for w in $(WIKI); do scp Doxygen/html/$$w.html $(MANUAL_DST); done

View File

@ -41,6 +41,8 @@
///
/// <ol>
/// <li>@ref HttpSimpleAll "POST /_api/simple/all"</li>
/// <li>@ref HttpSimpleByExample "POST /_api/simple/by-example"</li>
/// <li>@ref HttpSimpleFirstExample "POST /_api/simple/first-example"</li>
/// <li>@ref HttpSimpleNear "POST /_api/simple/near"</li>
/// <li>@ref HttpSimpleWithin "POST /_api/simple/within"</li>
/// </ol>
@ -71,13 +73,20 @@
/// @copydetails JSA_PUT_api_simple_all
/// <hr>
///
/// @anchor HttpSimpleByExample
/// @copydetails JSA_PUT_api_simple_by_example
/// <hr>
///
/// @anchor HttpSimpleFirstExample
/// @copydetails JSA_PUT_api_simple_first_example
/// <hr>
///
/// @anchor HttpSimpleNear
/// @copydetails JSA_PUT_api_simple_near
/// <hr>
///
/// @anchor HttpSimpleWithin
/// @copydetails JSA_PUT_api_simple_within
/// <hr>
////////////////////////////////////////////////////////////////////////////////
// Local Variables:

View File

@ -269,39 +269,96 @@ describe AvocadoDB do
it "finds the examples" do
body = "{ \"i\" : 1 }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
puts doc
doc.code.should eq(201)
doc.code.should eq(202)
d1 = doc.parsed_response['_id']
body = "{ \"i\" : 1, \"a\" : { \"j\" : 1 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(201)
doc.code.should eq(202)
d2 = doc.parsed_response['_id']
body = "{ \"i\" : 1, \"a\" : { \"j\" : 1, \"k\" : 1 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(201)
doc.code.should eq(202)
d3 = doc.parsed_response['_id']
body = "{ \"i\" : 1, \"a\" : { \"j\" : 2, \"k\" : 2 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(201)
doc.code.should eq(202)
d4 = doc.parsed_response['_id']
body = "{ \"i\" : 2 }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(201)
doc.code.should eq(202)
d5 = doc.parsed_response['_id']
body = "{ \"i\" : 2, \"a\" : 2 }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(201)
doc.code.should eq(202)
d6 = doc.parsed_response['_id']
body = "{ \"i\" : 2, \"a\" : { \"j\" : 2, \"k\" : 2 } }"
doc = AvocadoDB.post("/document?collection=#{@cid}", :body => body)
doc.code.should eq(201)
doc.code.should eq(202)
d7 = doc.parsed_response['_id']
cmd = api + "/by-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ { \"i\" : 1 } ] }"
doc = AvocadoDB.log_put("#{prefix}-by-example1", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['hasMore'].should eq(false)
doc.parsed_response['result'].length.should eq(4)
doc.parsed_response['count'].should eq(4)
doc.parsed_response['result'].map{|i| i['_id']}.should =~ [d1,d2,d3,d4]
cmd = api + "/by-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ { \"a\" : { \"j\" : 1 } } ] }"
doc = AvocadoDB.log_put("#{prefix}-by-example2", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['hasMore'].should eq(false)
doc.parsed_response['result'].length.should eq(1)
doc.parsed_response['count'].should eq(1)
doc.parsed_response['result'].map{|i| i['_id']}.should =~ [d2]
cmd = api + "/by-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ \"a.j\", 1 ] }"
doc = AvocadoDB.log_put("#{prefix}-by-example3", cmd, :body => body)
doc.code.should eq(201)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(201)
doc.parsed_response['hasMore'].should eq(false)
doc.parsed_response['result'].length.should eq(2)
doc.parsed_response['count'].should eq(2)
doc.parsed_response['result'].map{|i| i['_id']}.should =~ [d2,d3]
cmd = api + "/first-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ \"a.j\", 1, \"a.k\", 1 ] }"
doc = AvocadoDB.log_put("#{prefix}-first-example", cmd, :body => body)
doc.code.should eq(200)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(200)
doc.parsed_response['document']['_id'].should eq(d3)
cmd = api + "/first-example"
body = "{ \"collection\" : \"#{@cid}\", \"example\" : [ \"a.j\", 1, \"a.k\", 2 ] }"
doc = AvocadoDB.log_put("#{prefix}-first-example-not-found", cmd, :body => body)
doc.code.should eq(404)
doc.headers['content-type'].should eq("application/json")
doc.parsed_response['error'].should eq(true)
doc.parsed_response['code'].should eq(404)
end
end

View File

@ -1851,7 +1851,7 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
ReleaseCollection(collection);
return scope.Close(v8::ThrowException(
CreateErrorObject(TRI_ERROR_BAD_PARAMETER,
"usage: document(<path1>, <value1>, ...)")));
"usage: byExample(<path1>, <value1>, ...)")));
}
size_t n = argv.Length() / 2;

View File

@ -363,7 +363,17 @@ actions.defineHttp({
///
/// @EXAMPLES
///
/// @verbinclude api_simple7
/// Matching an attribute:
///
/// @verbinclude api-simple-by-example1
///
/// Matching an attribute which is a sub-document:
///
/// @verbinclude api-simple-by-example2
///
/// Matching an attribute within a sub-document:
///
/// @verbinclude api-simple-by-example3
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -398,7 +408,7 @@ actions.defineHttp({
}
else {
try {
var result = collection.byExample.apply(collection.byExample, example);
var result = collection.byExample.apply(collection, example);
if (skip != null) {
result = result.skip(skip);
@ -420,33 +430,34 @@ actions.defineHttp({
////////////////////////////////////////////////////////////////////////////////
/// @fn JSA_PUT_api_simple_first_example
/// @brief returns all documents of a collection matching a given example
/// @brief returns one document of a collection matching a given example
///
/// @REST{PUT /_api/simple/by-example}
/// @REST{PUT /_api/simple/first-example}
///
/// This will find all documents matching a given example.
/// This will return the first document matching a given example.
///
/// The call expects a JSON hash array as body with the following attributes:
///
/// @FA{collection}
/// - @LIT{collection}: The identifier or name of the collection to query.
///
/// The identifier or name of the collection to query.
/// - @LIT{example}: The example.
///
/// @FA{example}
/// - @LIT{skip}: The documents to skip in the query. (optional)
///
/// The example.
/// - @LIT{limit}: The maximal amount of documents to return. (optional)
///
/// @FA{skip} (optional)
///
/// The documents to skip in the query.
///
/// @FA{limit} (optional)
///
/// The maximal amount of documents to return.
/// Returns a result containing the document or @LIT{HTTP 404} if no
/// document matched the example.
///
/// @EXAMPLES
///
/// @verbinclude api_simple7
/// If a matching document was found:
///
/// @verbinclude api-simple-first-example
///
/// If no document was found:
///
/// @verbinclude api-simple-first-example-not-found
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
@ -460,16 +471,15 @@ actions.defineHttp({
return;
}
var limit = body.limit;
var skip = body.skip;
var name = body.collection;
var example = body.example;
if (req.requestType != actions.PUT) {
actions.unsupported(req, res);
}
else {
collection = internal.db._collection(name);
var example = body.example;
var name = body.collection;
var id = parseInt(name) || name;
var collection = internal.db._collection(id);
if (collection == null) {
actions.collectionNotFound(req, res, name);
@ -478,17 +488,14 @@ actions.defineHttp({
actions.badParameter(req, res, "example");
}
else {
var result = collection.byExample(example);
var result = collection.byExample.apply(collection, example).limit(1);
if (skip != null) {
result = result.skip(skip);
if (result.hasNext()) {
actions.resultOk(req, res, actions.HTTP_OK, { document : result.next() });
}
if (limit != null) {
result = result.limit(limit);
else {
actions.resultNotFound(req, res, "no match");
}
actions.resultOk(req, res, actions.HTTP_OK, result.toArray());
}
}
}

View File

@ -127,6 +127,61 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
///
/// @FUN{@FA{collection}.firstExample(@FA{path1}, @FA{value1}, ...)}
///
/// Returns the first documents of a collection that match the specified example
/// or @LIT{null}. The example must be specified as paths and
/// values. Allowed attribute types for searching are numbers, strings, and
/// boolean values.
///
/// @EXAMPLES
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.firstExample = function () {
// create a REAL array, otherwise JSON.stringify will fail
var example = [];
for (var i = 0; i < arguments.length; ++i) {
example.push(arguments[i]);
}
var data = {
collection : this._id,
example : example
}
var requestResult = this._database._connection.PUT("/_api/simple/first-example", JSON.stringify(data));
if (requestResult != null
&& requestResult.error == true
&& requestResult.errorNum == internal.errors.ERROR_HTTP_NOT_FOUND.code) {
return null;
}
TRI_CheckRequestResult(requestResult);
return requestResult.document;
}
AvocadoEdgesCollection.prototype.firstExample = AvocadoCollection.prototype.firstExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- SIMPLE QUERY NEAR
// -----------------------------------------------------------------------------

View File

@ -277,40 +277,19 @@ AvocadoEdgesCollection.prototype.geo = AvocadoCollection.geo;
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.byExample = function () {
return new SimpleQueryByExample(this, arguments);
// create a REAL array, otherwise JSON.stringify will fail
var example = [];
for (var i = 0; i < arguments.length; ++i) {
example.push(arguments[i]);
}
return new SimpleQueryByExample(this, example);
}
AvocadoEdgesCollection.prototype.byExample = AvocadoCollection.prototype.byExample;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
///
/// @FUN{@FA{collection}.firstExample(@FA{path1}, @FA{value1}, ...)}
///
/// Returns the first documents of a collection that match the specified example
/// or @LIT{null}. The example must be specified as paths and
/// values. Allowed attribute types for searching are numbers, strings, and
/// boolean values.
///
/// @EXAMPLES
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.firstExample = function () {
var cursor = new SimpleQueryByExample(this, arguments);
var result = null;
if (cursor.hasNext()) {
result = cursor.next();
}
cursor.dispose();
return result;
}
AvocadoEdgesCollection.prototype.firstExample = AvocadoCollection.prototype.firstExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -123,6 +123,47 @@ SQ.SimpleQueryByExample.prototype.execute = function () {
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup SimpleQuery
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a query-by-example for a collection
///
/// @FUN{@FA{collection}.firstExample(@FA{path1}, @FA{value1}, ...)}
///
/// Returns the first documents of a collection that match the specified example
/// or @LIT{null}. The example must be specified as paths and
/// values. Allowed attribute types for searching are numbers, strings, and
/// boolean values.
///
/// @EXAMPLES
////////////////////////////////////////////////////////////////////////////////
AvocadoCollection.prototype.firstExample = function () {
var cursor = new SimpleQueryByExample(this, arguments);
var result = null;
if (cursor.hasNext()) {
result = cursor.next();
}
cursor.dispose();
return result;
}
AvocadoEdgesCollection.prototype.firstExample = AvocadoCollection.prototype.firstExample;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- SIMPLE QUERY NEAR
// -----------------------------------------------------------------------------