ArangoDB verifiying query - arangodb

So I have an ArangoDB query here, but it throws an error while executed. It says syntax error and then says the error is somewhere around adminEdge._from but I can't find what the problem is :
let query = aql`
FOR user IN ${users}
FILTER user._key == ${body.userKey}
FOR adminEdge IN ${administrates}
FILTER adminEdge._from == user._id
LIMIT 1
RETURN { accountId: adminEdge._to, user }`;
users and administrates comes from db.collection that comes with ArangoDB.
body is an object that is passed in as a parameter.
I'm pretty new to AQL so maybe I'm making some basic errors

Since you are returning multiple columns, you cannot just return user, you have to list its columns just like you list adminEdge._to.

Camba is right, your return value is not valid.
You could try something like
FOR user IN ${users}
FILTER user._key == ${body.userKey}
FOR adminEdge IN ${administrates}
FILTER adminEdge._from == user._id
LIMIT 1
RETURN MERGE({accountId: adminEdge._to},user)

Related

Is it possible to get a detailed query when delete operation fails?

I am doing a delete operation with a filter of 2 fields:
const query = await Flow.deleteOne({
_id: flowId,
permissions: currentUser!.id,
});
Then I check the query object that returns from this operation to determine whether the operation was successful or not:
if (!query.deletedCount) {
throw new BadRequestError("Flow not found");
}
The problem is that I cant know if the operation failed because the flowId is wrong (first filter field) or the user don't have permissions (second filter field).
Is there an option to get a more detailed query result in mongoose?
As you can see from the official docs, deleteOne returns an object with three properties:
ok 1 if no errors
deletedCount number of docs deleted
n number of docs deleted
If you need to investigate the reasons for the failure you could query the database in case of error, something like:
if (!query.deletedCount) {
const flow = await Flow.findById(flowId);
// wrong `flowId`
if (!flow) throw new BadRequestError("Flow not found");
// otherwise, user don't have permission
throw new BadRequestError("Unauthorized");
}

Update multiple fields at once with QLDB Node.js driver

I'm trying to implement an API endpoint that handles PATCH or PUT requests, updating the relevant QLDB document with the request payload. I'm trying the following, but it doesn't seem to work:
await driver.executeLambda(async (txn) => {
await txn.execute(
`UPDATE People AS p BY p_id SET ? WHERE p_id = ?`,
requestPayload,
documentId,
);
});
The error I get is:
BadRequestException: Parser Error: at line 1, column 32: Invalid path component, expecting either an IDENTIFIER or STAR, got: QUESTION_MARK with value:
1; Expected identifier for simple path
(I have confirmed that the QLDB statement UPDATE People AS p BY p_id SET p.name = 'John Doe' WHERE p_id = '<document_id>', run in the QLDB web console, does in fact work as desired. I've also confirmed that the values of my variables are as I'd expect -- the first is an object and the second is a string.)
Is this kind of updating not supported by the QLDB Node.js driver?
It looks like your query is missing the field name in the parameterization. It should be SET p.name = ?:
UPDATE People AS p BY p_id SET p.name = ? WHERE p.p_id = ?

Why does MongoDB/Mongoose find query with null or undefined argument return all docs?

API requests same data from MongoDB with specific parameters. But I don't want to return any docs If query parameter are null or undefined. On the contrary, MongoDB returns all docs. Why and is this normal?
await exampleModel.find({}).lean().exec() // return all docs. That's okay.
await exampleModel.find(null).lean().exec() // return all docs. That's weird.
await exampleModel.find(undefined).lean().exec() // return all docs. That's weird.
Yes, this is normal. Perhaps MongoDB defaults to an empty filter ({}) when passing null or undefined or not passing a parameter at all (foo.find()). In any case the filter and the projection (the second parameter) are optional:
query: Specifies selection filter using query operators. To return all documents in a collection, omit this parameter or pass an empty document ({}).
projection: Specifies the fields to return in the documents that match the query filter. To return all fields in the matching documents, omit this parameter.
If you want to not return anything if the query is null or undefined you can build it like this:
const results = query ? await exampleModel.find(query).lean.exec() : []

MongoDB count and get the limited data

I'm trying to get the count all the data for the query and as well as get the limited data (for pagination) but both the console output gives me the count.
What is that I'm doing wrong.
Pls help
const curFind = fbUser.find(find, 'firstName gender age birthday facebookId profileURL email imageUrl preferences blocked flames likes rejects location reported')
curFind.count(function(e, count) {
console.log(count);
curFind.skip(0).limit(10).hint( { $natural : 1 } ).exec(function(err, data) {
console.log(data);
});
});
If you print the curFind object before and after executing count, you will notice that the Query object's op field changes from find to count. It may or may not be a bug with mongoose, but explains why you are getting a count again. I generally don't re-use the query object - which would solve your issue too.

nodejs: save function in for loop, async troubles

NodeJS + Express, MongoDB + Mongoose
I have a JSON feed where each record has a set of "venue" attributes (things like "venue name" "venue location" "venue phone" etc). I want to create a collection of all venues in the feed -- one instance of each venue, no dupes.
I loop through the JSON and test whether the venue exists in my venue collection. If it doesn't, save it.
jsonObj.events.forEach(function(element, index, array){
Venue.findOne({'name': element.vname}, function(err,doc){
if(doc == null){
var instance = new Venue();
instance.name = element.vname;
instance.location = element.location;
instance.phone = element.vphone;
instance.save();
}
}
}
Desired: A list of all venues (no dupes).
Result: Plenty of dupes in the venue collection.
Basically, the loop created a new Venue record for every record in the JSON feed.
I'm learning Node and its async qualities, so I believe the for loop finishes before even the first save() function finishes -- so the if statement is always checking against an empty collection. Console.logging backs this claim up.
I'm not sure how to rework this so that it performs the desired task. I've tried caolan's async module but I can't get it to help. There's a good chance I'm using incorrectly.
Thanks so much for pointing me in the right direction -- I've searched to no avail. If the async module is the right answer, I'd love your help with how to implement it in this specific case.
Thanks again!
Why not go the other way with it? You didn't say what your persistence layer is, but it looks like mongoose or possibly FastLegS. In either case, you can create a Unique Index on your Name field. Then, you can just try to save anything, and handle the error if it's a unique index violation.
Whatever you do, you must do as #Paul suggests and make a unique index in the database. That's the only way to ensure uniqueness.
But the main problem with your code is that in the instance.save() call, you need a callback that triggers the next iteration, otherwise the database will not have had time to save the new record. It's a race condition. You can solve that problem with caolan's forEachSeries function.
Alternatively, you could get an array of records already in the Venue collection that match an item in your JSON object, then filter the matches out of the object, then iteratively add each item left in the filtered JSON object. This will minimize the number of database operations by not trying to create duplicates in the first place.
Venue.find({'name': { $in: jsonObj.events.map(function(event){ return event.vname; }) }}, function (err, docs){
var existingVnames = docs.map(function(doc){ return doc.name; });
var filteredEvents = jsonObj.events.filter(function(event){
return existingVnames.indexOf(event.vname) === -1;
});
filteredEvents.forEach(function(event){
var venue = new Venue();
venue.name = event.vname;
venue.location = event.location;
venue.phone = event.vphone;
venue.save(function (err){
// Optionally, do some logging here, perhaps.
if (err) return console.error('Something went wrong!');
else return console.log('Successfully created new venue %s', venue.name);
});
});
});

Resources