简体   繁体   中英

ArangoDB - How do you refer to OLD in an upsert statement using AQB

I want to create an upsert statement like this:

upsert {_from: @uid, _to: t._id}
insert { _from: @uid, _to: t._id, like: 1}
update {like: OLD.like+1}
in edge

Using AQB, how do I refer to OLD.like, as an integer and increment by 1?

...
.upsert({_from: '@uid', _to: "t._id"})                                                                                                                                                           
.insert({_from: '@uid', _to: 't._id', like:1})                                                                                                                                                   
.update({like: aqb.get('OLD', aqb.ref('like'))+1})                                                                                                                                               
.in("edge")
...

This actually has nothing to do with UPSERT. The problem is that you're using the plus operator in JavaScript, which tries to convert the expression aqb.get('OLD', aqb.ref('like')) to a string and append '1' to it. In JS operators can't be overloaded, so AQB can't prevent you from doing that.

The correct expression would be aqb.get('OLD', aqb.ref('like')).add(1) , which generates the following AQL:

UPSERT {_from: @uid, _to: t._id}
INSERT {_from: @uid, to: t._id, like: 1}
UPDATE {like: (`OLD`[like] + 1)}
IN edge

Also note that this tries to use like as a variable for the name of the attribute. That's probably not what you want. Instead you'd use aqb.str('like') or simply aqb('like') (resulting in OLD["like"] ).

You can actually simplify this a bit. OLD.like is a valid simple reference in AQB, so you can simply use aqb.ref('OLD.like').add(1) . Or you can simplify it further by using the add function directly: aqb.add('OLD.like', 1) . All of these are semantically equivalent and should generate semantically equivalent (if not identical) AQL. Here's the AQL generated by the last example:

UPSERT {_from: @uid, _to: t._id}
INSERT {_from: @uid, to: t._id, like: 1}
UPDATE {like: (`OLD`.like + 1)}
IN edge

As far as I can see it can be achieved like this:

/* search values */
FROM = "v/1";
TO   = "v/2"; 

var qb = require("aqb"); 
q = qb.upsert({ _from: qb.str(FROM), _to: qb.str(TO) })
      .insert({ _from : qb.str(FROM), _to: qb.str(TO), like: 1 })
      .update({ like: qb.plus(qb.get("OLD", qb.str("like")), 1) })
      .in("edge")
      .returnOld("old"); 

/* to verify the generated AQL string */
print(q.toAQL());

This constructs the following AQL query

UPSERT {_from: "v/1", _to: "v/2"} 
INSERT {_from: "v/1", _to: "v/2", like: 1} 
UPDATE {like: (`OLD`["like"] + 1)} IN edge 
LET `old` = OLD 
RETURN `old`

which is hopefully what you were looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM