How to use AQL functions inside user defined functions? - arangodb

Is it possible to use standard AQL functions inside a user-defined function ?
I tried to call IS_IN_POLYGON() inside a custom function and got this error at execution time :
Query: AQL: in function 'GEO::IS_IN_MULTIPOLYGON()': user function runtime error: ReferenceError: IS_IN_POLYGON is not defined at (…)
Is there any prefix / require() / anything, that should be used to access standard AQL functions ?
ArangoDB version : 3.2.4
Engine : RocksDB

Yes, one can use AQL functions, including other UDFs, inside UDF functions.
Here is a complete example, using the AQL function LENGTH():
aqlfunctions.register('TEST::test', function(collection) {
'use strict';
const db = require('#arangodb').db;
const AQL_FUNCTION = db._query;
return (typeof collection == "string")
? AQL_QUERY('RETURN LENGTH(' + collection + ')').toArray()[0]
: return typeof collection;
}, false);
To use a UDF function, simply include its namespace (e.g. ARRAY::PRODUCT) in the way you'd use in an AQL query.
Caveat: UDFs must be side-effect free. They are not supposed to alter the database state in any way.
The ArangoDB documentation is not entirely clear what complications may arise if the return value of a UDF depends in any way on the database state (as in the above example).

Answering my own question here.
One can use AQL functions inside a user defined function this way :
(example for fictitious SOME_AQL_FUNCTION() returning a boolean)
let result = AQL_QUERY("RETURN SOME_AQL_FUNCTION(…)").json[0];
Found that reading some test code on ArangoDB's GitHub.

Related

How to do pattern matching query in node-oracledb

I am trying to execute a simple query with pattern matching using LIKE in the WHERE clause using node-oracledb NodeJS library, however I can't seem to figure out how to do it. This doesn't seem to work
const baseQuery =
`select item, item_desc
from item_master
where item_level=tran_level
and item like '%:item%'`;
const binds = { item: '550' };
const result = await conn.execute(baseQuery, binds, {});
It keeps throwing the error below-
[Error: ORA-01036: illegal variable name/number] {
errorNum: 1036,
offset: 0
}
I've read the node-oracledb documentation but this seemingly simple use case of pattern match queries doesn't seem to be documented anywhere. Is pattern matching supported? if yes, then what am I doing wrong?
This was answered in your cross post at https://github.com/oracle/node-oracledb/issues/1195
Use a normal bind variable in the SQL statement (which is important for scalability and security, so that data is never treated as part of the SQL statement). Then concatenate whatever pattern matching syntax you want to the data.
To quote sla100's answer in the GitHub issue:
SQL:
and item like :item
JS:
const binds = { item: '%550%' };
You can do this with LIKE comparisons and also REGEXP_LIKE. The node-oracledb documentation also has examples of doing this in WHERE IN.

mongo db virtual get function how to return document

details:mongodb,mongoose,nodejs
example :
schema.virtual(''name').get(function() => {
return this.anything;
})
how the this key work to point document?
Is get method return document?
Might be a typo in the post but your string starts with two quotes.
You are mixing up the syntax for regular functions and arrow functions.
Do this:
schema.virtual('name').get(function() {
return this.anything;
});
You cannot use an arrow function in this situation anyway since arrow functions do not allow the rebinding of the this context.

Making Mongoose/MongoDB query helper plugin return zero results

I'm developing a Mongoose Query Helper plugin that provides the chainable method .search(query). On certain conditions, I want the query to return zero results, no matter how the other methods in the query builder chain behave. Turns out this isn't so easy as I have assumed.
Basically, I have the following code:
schema.query.search = function search(query) {
if ("query is invalid") {
// return no results => no easy way to achieve that?
}
return this.find(query);
};
Now, I want SomeModel.find({}).search(someQuery).exec() to return no results in case the query is invalid. I first tried to return this.limit(0), but turns out a limit of 0 is equivalent to setting no limit.
As a temporary solution, I do return this.find({ nonExistingField: 'something' }) which always results in no results, but this does seem a bit awkward and is probably also not so optimal in terms of performance as it triggers a search when no search is needed.
Thanks in advance for your help!

Azure Search - Error

When trying to index documents we are getting this error:
{"Token PropertyName in state ArrayStart would result in an invalid JSON object. Path 'value[0]'."}
Our code for indexing using the .NET library is :
using (var indexClient = new SearchIndexClient(searchServiceName, indexName, new SearchCredentials(apiKey)))
{
indexClient.Documents.Index(IndexBatch.Create(IndexAction.Create(documents.Select(doc => IndexAction.Create(doc)))));
}
Does anyone know why this error occurs?
The issue is because of an extra call to IndexAction.Create. If you change your indexing code to this, it will work:
indexClient.Documents.Index(IndexBatch.Create(documents.Select(doc => IndexAction.Create(doc))));
The compiler didn't catch this because IndexBatch.Create has a params argument that can take any number of IndexAction<T> for any type T. In this case, T was a collection, which is not supported (documents must be objects, not collections).
The programming model for creating batches and actions is changing substantially in the 1.0.0-preview release of the SDK. It will be more type-safe so that mistakes like this are more likely to be caught at compile-time.

Passing parameters to db.query with arangojs

I'm having problems sending parameters with the ArangoJS library and was wondering if anyone could help.
With the example below, it is possible to execute db.query if parameter values are in the query, but as soon as I try to use bindVars I get silent errors and I can't extract any error details.
var db = require('arangojs')("http://127.0.0.1:8529");
/*
The '_system' database contains a collection called 'test' that contains one document:
{
"a": 1,
"b": 2
}
*/
// This works
db.query('FOR t IN test FILTER t.a == 1 RETURN t')
.then((cursor) => {
cursor.all()
.then(vals => {
console.log("\nNo bindVars");
console.log(vals);
});
});
// This does not work
db.query("FOR t IN #first FILTER t.a == #second RETURN t", { first: "test", second: 1 })
.then((cursor) => {
cursor.all()
.then(vals => {
console.log("\nUsing bindVars");
console.log(vals);
});
});
I'm new to Node.js and ArangoDB and would love to be able to use properly parameterized queries.
I'm also assuming that this use of parameters protects you from SQL Injection style attacks?
Thanks!
The problem isn't with the JavaScript driver or Node, the problem is with the query itself:
FOR t IN #first FILTER t.a == #second RETURN t
In AQL collection names can't be injected with ordinary bind parameters. This is because you're not actually trying to use the parameter as a string value but to refer to a collection with that name. To quote the AQL documentation:
A special type of bind parameter exists for injecting collection names. This type of bind parameter has a name prefixed with an additional # symbol (thus when using the bind parameter in a query, two # symbols must be used).
In other words, in AQL it has to be called ##first (instead of #first) and in the bind parameters argument to db.query it has to be called #first (instead of just first).
When using arangojs it's actually possible to avoid this entirely by using the aqlQuery template handler:
var aqlQuery = require('arangojs').aqlQuery;
var first = db.collection('test');
var second = 1;
db.query(aqlQuery`
FOR t IN ${first}
FILTER t.a == ${second}
RETURN t
`).then(
cursor => cursor.all()
).then(vals => {
console.log('Using aqlQuery');
console.log(vals);
});
This way you don't have to think about bind parameter syntax when writing queries and can write more complex queries without having to mess with extremely long strings. Note that it will recognize arangojs collection instances and handle them accordingly. Using a string instead of a collection instance would result in the same problems as in your example.
Additionally note that the template handler also exists in the arangosh shell and in ArangoDB itself (e.g. when using Foxx).

Resources