mirror of https://gitee.com/bigwinds/arangodb
added AQL functions KEEP() and UNSET()
This commit is contained in:
parent
3d47748434
commit
3e04acf3ee
|
@ -1,6 +1,8 @@
|
|||
v1.2.alpha (XXXX-XX-XX)
|
||||
-----------------------
|
||||
|
||||
* added AQL functions KEEP() and UNSET()
|
||||
|
||||
* fixed issue #348: "HTTP Interface for Administration and Monitoring"
|
||||
documentation errors.
|
||||
|
||||
|
|
|
@ -154,6 +154,10 @@ in ArangoDB 1.2:
|
|||
|
||||
* `ATTRIBUTES()`: returns the names of all attributes of a document as a list
|
||||
|
||||
* `KEEP()`: keeps only the specified attributes of a document, and removes all others
|
||||
|
||||
* `UNSET()`: removes only the specified attributes from a document, and preserves all others
|
||||
|
||||
* `MATCHES()`: to check if a document matches one of multiple example documents
|
||||
|
||||
* `LIKE()`: pattern-based text comparison
|
||||
|
|
|
@ -1032,6 +1032,20 @@ AQL supports the following functions to operate on document values:
|
|||
`_key` etc.) are removed from the result. If @FA{sort} is set to `true`, then the
|
||||
attribute names in the result will be sorted. Otherwise they will be returned in any order.
|
||||
|
||||
- @FN{UNSET(@FA{document}\, @FA{attributename}\, ...)}: removes the attributes @FA{attributename}
|
||||
(can be one or many) from @FA{document}. All other attributes will be preserved.
|
||||
Multiple attribute names can be specified by either passing multiple individual string argument
|
||||
names, or by passing a list of attribute names:
|
||||
|
||||
RETURN UNSET(doc, '_id', '_key', [ 'foo', 'bar' ])
|
||||
|
||||
- @FN{KEEP(@FA{document}\, @FA{attributename}\, ...)}: keeps only the attributes @FA{attributename}
|
||||
(can be one or many) from @FA{document}. All other attributes will be removed from the result.
|
||||
Multiple attribute names can be specified by either passing multiple individual string argument
|
||||
names, or by passing a list of attribute names:
|
||||
|
||||
RETURN KEEP(doc, 'firstname', 'name', 'likes')
|
||||
|
||||
@subsubsection AqlFunctionsGeo Geo functions
|
||||
|
||||
AQL offers the following functions to filter data based on geo indexes:
|
||||
|
|
|
@ -625,6 +625,8 @@ TRI_associative_pointer_t* TRI_InitialiseFunctionsAql (void) {
|
|||
REGISTER_FUNCTION("MERGE_RECURSIVE", "MERGE_RECURSIVE", true, false, "a,a|+", NULL);
|
||||
REGISTER_FUNCTION("DOCUMENT", "DOCUMENT", false, false, "h,sl", NULL);
|
||||
REGISTER_FUNCTION("MATCHES", "MATCHES", true, false, ".,l|b", NULL);
|
||||
REGISTER_FUNCTION("UNSET", "UNSET", true, false, "a,sl|+", NULL);
|
||||
REGISTER_FUNCTION("KEEP", "KEEP", true, false, "a,sl|+", NULL);
|
||||
|
||||
// geo functions
|
||||
REGISTER_FUNCTION("NEAR", "GEO_NEAR", false, false, "h,n,n,n|s", NULL);
|
||||
|
|
|
@ -354,6 +354,34 @@ function VALUES (value) {
|
|||
return values;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract key names from an argument list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function EXTRACT_KEYS (args, startArgument, functionName) {
|
||||
var keys = { }, i, j, key, key2;
|
||||
|
||||
for (i = startArgument; i < args.length; ++i) {
|
||||
key = args[i];
|
||||
if (typeof key === 'string') {
|
||||
keys[key] = true;
|
||||
}
|
||||
else if (Array.isArray(key)) {
|
||||
for (j = 0; j < key.length; ++j) {
|
||||
key2 = key[j];
|
||||
if (typeof key2 === 'string') {
|
||||
keys[key2] = true;
|
||||
}
|
||||
else {
|
||||
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, functionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the keys of an array or object in a comparable way
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2330,6 +2358,54 @@ function ATTRIBUTES (element, removeInternal, sort) {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief unset specific attributes from a document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function UNSET (value) {
|
||||
if (TYPEWEIGHT(value) !== TYPEWEIGHT_DOCUMENT) {
|
||||
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "UNSET");
|
||||
}
|
||||
|
||||
var keys = EXTRACT_KEYS(arguments, 1, "UNSET"), i;
|
||||
|
||||
var result = { };
|
||||
// copy over all that is left
|
||||
for (i in value) {
|
||||
if (value.hasOwnProperty(i)) {
|
||||
if (keys[i] !== true) {
|
||||
result[i] = CLONE(value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief keep specific attributes from a document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function KEEP (value) {
|
||||
if (TYPEWEIGHT(value) !== TYPEWEIGHT_DOCUMENT) {
|
||||
THROW(INTERNAL.errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH, "KEEP");
|
||||
}
|
||||
|
||||
var keys = EXTRACT_KEYS(arguments, 1, "KEEP"), i;
|
||||
|
||||
// copy over all that is left
|
||||
var result = { };
|
||||
for (i in keys) {
|
||||
if (keys.hasOwnProperty(i)) {
|
||||
if (value.hasOwnProperty(i)) {
|
||||
result[i] = CLONE(value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief merge all arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2980,6 +3056,8 @@ exports.FIRST_LIST = FIRST_LIST;
|
|||
exports.FIRST_DOCUMENT = FIRST_DOCUMENT;
|
||||
exports.HAS = HAS;
|
||||
exports.ATTRIBUTES = ATTRIBUTES;
|
||||
exports.UNSET = UNSET;
|
||||
exports.KEEP = KEEP;
|
||||
exports.MERGE = MERGE;
|
||||
exports.MERGE_RECURSIVE = MERGE_RECURSIVE;
|
||||
exports.MATCHES = MATCHES;
|
||||
|
|
|
@ -913,6 +913,69 @@ function ahuacatlFunctionsTestSuite () {
|
|||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { QUERY("RETURN RAND(2)"); } ));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test keep function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testKeepInvalid : function () {
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN KEEP({ }, 1)"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN KEEP({ }, { })"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN KEEP({ }, 'foo', { })"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN KEEP('foo', 'foo')"); } ));
|
||||
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { QUERY("RETURN KEEP()"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { QUERY("RETURN KEEP({ })"); } ));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test keep function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testKeep : function () {
|
||||
var actual, expected;
|
||||
|
||||
actual = getQueryResults("FOR i IN [ { }, { foo: 1, bar: 2, moo: 3, goof: 4, bang: 5, meow: 6 }, { foo: 0, goof: 1, meow: 2 }, { foo: null }, { foo: true }, { goof: null } ] RETURN KEEP(i, 'foo', 'bar', 'baz', [ 'meow' ], [ ])", false);
|
||||
assertEqual([ { }, { bar: 2, foo: 1, meow: 6 }, { foo: 0, meow: 2 }, { foo: null }, { foo: true }, { } ], actual);
|
||||
|
||||
actual = getQueryResults("FOR i IN [ { }, { foo: 1, bar: 2, moo: 3, goof: 4, bang: 5, meow: 6 }, { foo: 0, goof: 1, meow: 2 }, { foo: null }, { foo: true }, { goof: null } ] RETURN KEEP(i, [ 'foo', 'bar', 'baz', 'meow' ])", false);
|
||||
assertEqual([ { }, { bar: 2, foo: 1, meow: 6 }, { foo: 0, meow: 2 }, { foo: null }, { foo: true }, { } ], actual);
|
||||
|
||||
actual = getQueryResults("FOR i IN [ { }, { foo: 1, bar: 2, moo: 3, goof: 4, bang: 5, meow: 6 }, { foo: 0, goof: 1, meow: 2 }, { foo: null }, { foo: true }, { goof: null } ] RETURN KEEP(i, 'foo', 'bar', 'baz', 'meow')", false);
|
||||
assertEqual([ { }, { bar: 2, foo: 1, meow: 6 }, { foo: 0, meow: 2 }, { foo: null }, { foo: true }, { } ], actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test unset function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testUnsetInvalid : function () {
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN UNSET({ }, 1)"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN UNSET({ }, { })"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN UNSET({ }, 'foo', { })"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, getErrorCode(function() { QUERY("RETURN UNSET('foo', 'foo')"); } ));
|
||||
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { QUERY("RETURN UNSET()"); } ));
|
||||
assertEqual(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, getErrorCode(function() { QUERY("RETURN UNSET({ })"); } ));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test unset function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testUnset : function () {
|
||||
var expected = [ { bang: 5, goof: 4, moo: 3 }, { goof: 1 }, { }, { }, { goof: null } ];
|
||||
var actual;
|
||||
|
||||
actual = getQueryResults("FOR i IN [ { foo: 1, bar: 2, moo: 3, goof: 4, bang: 5, meow: 6 }, { foo: 0, goof: 1, meow: 2 }, { foo: null }, { foo: true }, { goof: null } ] RETURN UNSET(i, 'foo', 'bar', 'baz', [ 'meow' ], [ ])", false);
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = getQueryResults("FOR i IN [ { foo: 1, bar: 2, moo: 3, goof: 4, bang: 5, meow: 6 }, { foo: 0, goof: 1, meow: 2 }, { foo: null }, { foo: true }, { goof: null } ] RETURN UNSET(i, [ 'foo', 'bar', 'baz', 'meow' ])", false);
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = getQueryResults("FOR i IN [ { foo: 1, bar: 2, moo: 3, goof: 4, bang: 5, meow: 6 }, { foo: 0, goof: 1, meow: 2 }, { foo: null }, { foo: true }, { goof: null } ] RETURN UNSET(i, 'foo', 'bar', 'baz', 'meow')", false);
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test merge function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue