Add edge between two documents in ArangoDB - arangodb

It should be easy operation but I can't find how to achieve this.
I have two documents from different collections and now I want to link them using new Edge from existing collection. I'm trying to use edge-collection.save function like this:
edge-collection.save(FOR s IN Sy
FILTER s._key=403560128,FOR i IN Im
FILTER i._key=353031872, points) but it doesn't work. How can I do this?

edge-collection.save() does not expect AQL statements as you are trying to insert. It is expecting raw _id attributes for from and to and as a thir parameter a JSON Object containing additional data for the edge.
To store the edge described in your example you can execute the following command:
edge-collection.save("Sy/403560128", "Im/353031872", points);
^^^^^ ^^^^^ ^^^^
sourceId targetId JSON

Related

flux query: filter out all records related to one matching the condition

I'm trying to filter an influx DB query (using the nodeJS influxdb-client library).
As far as I can tell, it only works with "flux" queries.
I would like to filter out all records that share a specific attribute with any record that matches a particular condition. I'm filtering using the filter-function, but I'm not sure how I can continue from there. Is this possible in a single query?
My filter looks something like this:
|> filter(fn:(r) => r["_value"] == 1 and r["button"] == "1" ) and I would like to leave out all the record that have the same r["session"] as any that match this filter.
Do I need two queries; one to get those r["session"]s and one to filter on those, or is it possible in one?
Update:
Trying the two-step process. Got the list of r["session"]s into an array, and attempting to use the contains() flux function now to filter values included in that array called sessionsExclude.
Flux query section:
|> filter(fn:(r) => contains(value: r["session"], set: ${sessionsExclude}))
Getting an error unexpected token for property key: INT ("102")'. Not sure why. Looks like flux tries to turn the values into Integers? The r["session"] is also a String (and the example in the docs also uses an array of Strings)...
Ended up doing it in two queries. Still confused about the Strings vs Integers, but casting the value as an Int and printing out the array of r["session"] within the query seems to work like this:
'|> filter(fn:(r) => not contains(value: int(v: r["session"]), set: [${sessionsExclude.join(",")}]))'
Added the "not" to exclude instead of retain the values matching the array...

ArangoDB - Swap _to and _from values for edge using AQL

Is there a clean way to swap the _to and _from values for an edge using AQL? According to Arango's documentation on Edges:
To change edge endpoints you would need to remove old document/edge and insert new one. Other fields can be updated as in default collection.
So what I was able to come up with was a query that looks like this:
FOR edge IN edge_collection
FILTER [some criteria]
LET tempEdge = KEEP(edge, ATTRIBUTES(edge, true))
LET newEdge = MERGE([{'_key':edge._key}, {'_from':edge._to}, {'_to':edge._from}, tempEdge])
REPLACE newEdge IN edge_collection
RETURN NEW
To explain my own solution a bit, I used the ATTRIBUTES(edge, true) function to get the names of all of the Attributes on the Edge, and the true parameter removed the internal attributes (like _key, _id, _to, etc.). Read more about ATTRIBUTES here.
Then the KEEP(edge, [attributes]) function returns a new Document that only has the Attributes specified in the given array, which thanks to the ATTRIBUTES function in this case, is everything but the internal fields. Read more about KEEP here.
Then I use the MERGE function to combine the _key from the original edge, swap the _to and _from values, and all of the non-internal attributes. Read more about MERGE here.
Lastly, I use REPLACE which removes the original edge and adds the new one in, just like Arango requires. Read more about REPLACE here.
Like I said, this appears to work, but the MERGE in particular feels like the wrong way to go about doing what I did. Is there an easier way to set values on an Object? For instance, something that would let me just make a call similar to: tempEdge._from = edge._to?
Yes, there is a simpler solution:
FOR edge IN edge_collection
FILTER [some criteria]
UPDATE edge WITH {_from: edge._to, _to: edge._from} IN edge_collection
RETURN NEW
_from and _to can be updated (in contrast to the system attributes _id, _key and _rev), so you don't need to replace the whole document. And since UPDATE merges the changes into the existing document, you only need to specify the new values for _from and _to.

Sum or Difference operation of two keys in document using Mongoengine

I have defined a model like
Class Orders(Document):
orderAmount = fields.FloatField()
cashbackAmount = fields.FloatField()
meta = {'strict': False}
I want to get all orders where (orderAmount - cashbackAmount value > 500). I am using Mongoengine and using that I want to perform this operation. I am not using Django Framework so I cannot use solutions of that.
Let's approach this if you had to do this without Mongoengine. You would start by dividing this problem into two steps
1) How to get the difference between two fields and output it as the new field?
2) How to filter all the documents based on that field's value?
You can see that it consists of several steps, so it looks like a great use case for the aggregation framework.
The first problem can be solved using addFields and subtract operators.
{$addFields: {difference: {$subtract: ["$a", "$b"]}}}
what can be translated into "for every document add a new field called difference where difference=a-b".
The second problem is a simple filtering:
{$match: {difference:{$gt: 500}}}
"give me all documents where difference field is greater than 500"
So the whole query in MongoDB would look like this
db.collectionName.aggregate([{$addFields: {difference: {$subtract: ["$a", "$b"]}}}, {$match: {difference:{$gt: 500}}}])
Now we have to translate it into Mongoengine. It turns out that there is aggregate method defined, so we can easily make small adjustments to make this query work.
Diff.objects.aggregate({"$addFields": {"difference": {"$subtract": ["$a", "$b"]}}}, {"$match": {"difference":{"$gt": 500}}})
As a result, you get CommandCursor. You can interact with that object or just convert it to the list, to get a list of dictionaries.

orientjs: query result Bag.all() returns empty array

Im using OrientJS with nodeJS to perform a query using .query() method.
I get results, but I cant extract the in_ and out_ fields, as they`re of a 'Bag' type.
When I try .all() method to get the results I get an array[0].
When I perform the same query in Studio I see that the in_ and out_ fields are not empty.
Our edges are tree based, and tree based ridbags are not currently supported by OrientJs as can be seen here. This is why we did not get any results.
Embedded RIDbags are supported.

How to query models by a property that is an array

I'm trying to do a 'findOne' operation in a model that has an array property and filter the results to only list the item if the string im searching is in that array.
Example:
var AppUser = server.loopback.getModel('AppUser');
AppUser.create({
"name":"juan"
"favoriteLetters":["a","b","c"]
},function(){
AppUser.findOne({where:{favoriteLetters:'a'}},function(error,appUser){
console.log(error,appUser);
});
});
So in this case i want to find a 'appUser' that has a favorite letter 'a'.
Thanks.
As far as I understood, possibility of such kind of a query depends on the underlying datasource and is not supported yet for relational DBs. But should be fine with memory storage or mongodb. More details and syntax for query is here: https://groups.google.com/d/msg/loopbackjs/8c8kw8EMiPU/yev3lsmrTFUJ
For anyone else who lands here, that query in your model is correct (for Mongo anyways).
{where:{favoriteLetters:'a'}
Reference:
Find document with array that contains a specific value

Resources