Loopback Find then update attribute or delete by id - node.js

Been trying to find samples usage for some of the static methods for a persistedModel in Loopback.
https://apidocs.strongloop.com/loopback/#persistedmodel-prototype-updateattribute
it just says:
persistedModel.updateAttributes(data, callback)
But how you I choose the which record I want to update? this is not working for me.
var order = Order.setId('whateverrecordId');
order.updateAttributes({name:'new name'},callback)
Loving loopback.. but their doc, sucks.. :(

You can use those on event listener like AfterSave
example:
Model.observe('after save', function(ctx, next) {
ctx.instance.updateAttribute(fieldname:'new value');
next();
});

1- What you did was right but i do not advise this method it's used for instance methods and generally to update fields like date for all the collection that you have so you don't need an id for it.
But you can try to make an array containing data to update containing also the ids and then make a comparison to fill in data for the ids that you have. (in #dosomething)
order.find().then(function(orders) {
orders.forEach(function(element) {
order.setId(element.id);
#DoSomething
order.updateAttribute({new: data}, function(err, instance) {
console.log(instance);
})
});
})
2- You can use updateAll to update one or many attribute.
PersistedModel.updateAll([where], data, callback)
var Updates = [{id : 1, name: name1}, ...]
Updates.forEach(function(element) {
order.updateAll({id : element.id}, {name :element.name}, function(err, count) {
if (err) {
console.error(err);
}
console.log(count); // number of data updated
})
})

Related

Mongoose - Modle.update() updates wrong document - Cast Error

I need some help to clear some things up.
I have a Model:
var Event = new Schema({
event_code: String
, segments: [Segment]
});
The creation of new documents work very well like perfect. When it comes to update certain documents I ran into some troubles.
When I do this (code below): = it only updates the first document, even if the id does not match
function edit_event (id, new_name, callback) {
Event.update(id, {$set:{event_code: new_name}}, function(err, doc) {
if (err) throw err;
callback();
});
}
When I do this (code below): = it gives me an Error (see below)
function edit_event (id, new_name, callback) {
Event.findByIdAndUpdate(id, {$set:{event_code: new_name}}, function(err, doc) {
if (err) throw err;
callback();
});
}
Error when using findByIdAndUpdate: Cast to ObjectId failed for value ""58fdbde31bff83141b376508"" at path "_id" for model "Event"
Please, i'm desperate :! :/
UPDATE
I figured out that the id that i'm trying to pass get stored with "" around it, so when i am looking for document with matching ID it puts an extra pair of "" around it so it ends up like ""id""
UPDATE 2
When I am listing all my documents, it returns:
{ _id: 58fdbde31bff83141b376508,
event_code: 'TestABC',
__v: 0,
segments: [] }
Then when i store the id in an HTML form it adds extra pair of "" around it ... that's not the case with event_code. Why is that ?
Looks like you performed unneeded JSON.stringify and that's why you get quotes around the id. Calling JSON.parse should solve the issue:
Event.findByIdAndUpdate(JSON.parse(id), {$set:{event_code: new_name}}, ...

Mongoose doesn't update my fields

I'm trying to update an entries, if they are found in my Mongo DB:
exports.insert = function(project, data) {
data.forEach(function(d){
d.project = project;
var asset = new Asset(d);
Asset.findOne({
project: asset.project,
ip: asset.ip
}, function(err, match) {
if (err) { return next(err); }
if (match) {
console.log('asset found, updating');
match.mac = 'blablah';
match.save();
}
});
});
};
I also tried to update like this:
asset.mac = 'blalah';
match.update(asset);
In both cases my fields don't update in the DB. I see no change.
There may be smarter ways to do this but I need to be able to use save or update to do it for future.
NB: Although findOneAndUpdate may be the preferred way of doing this, I'm really curious to know why save() or update() do not work in my case. I would like to know how to use those methods to update my document.
If you're trying to find one entry and update it, you should use findOneAndUpdate:
Asset.findOneAndUpdate({
project: asset.project,
ip: asset.ip
}, {
mac: 'blablah'
}, function (err, docThatWasUpdated) {
....
})

how to improve the view with map/reduce in couchdb and nodejs

I'm using nodejs with the module cradle to interact with the couchdb server, the question is to let me understanding the reduce process to improve the view query...
For example, I should get the user data from his ID with a view like this:
map: function (doc) { emit(null, doc); }
And in node.js (with cradle):
db.view('users/getUserByID', function (err, resp) {
var found = false;
resp.forEach(function (key, row, id) {
if (id == userID) {
found = true;
userData = row;
}
});
if (found) {
//good, works
}
});
As you can see, this is really bad for large amount of documents (users in the database), so I need to improve this view with a reduce but I don't know how because I don't understand of reduce works.. thank you
First of all, you're doing views wrong. View are indexes at first place and you shouldn't use them for full-scan operations - that's ineffective and wrong. Use power of Btree index with key, startkey and endkey query parameters and emit field you like to search for as key value.
In second, your example could be easily transformed to:
db.get(userID, function(err, body) {
if (!err) {
// found!
}
});
Since in your loop you're checking row's document id with your userID value. There is no need for that loop - you may request document by his ID directly.
In third, if your userID value isn't matches document's ID, your view should be:
function (doc) { emit(doc.userID, null); }
and your code will be looks like:
db.view('users/getUserByID', {key: userID}, function (err, resp) {
if (!err) {
// found!
}
});
Simple. Effective. Fast. If you need matched doc, use include_docs: true query parameter to fetch it.

How to query data from different collections and sort by date?

I stumbled upon problem that my search results are of a mixed data, which is located in different collections (posts/venues/etc), currently Im doing separate requests to retrieve this data, but its obviously sorted among its types (posts array, venues array)
How can I query multiple collections (posts/venues) and sort them by date/any other parameter (via mongoose)?
or maybe there is a better solution?
Thanks
I believe its not possible with Mongoose, you can in the meanwhile do something like this:
var async = require('async');
function getPosts(cb) {
Post.find({"foo": "bar"}, function(err, posts) {
cb(err, posts);
})
}
function getVenues(cb) {
Venue.find({"foo": "bar"}, function(err, venues) {
cb(err, venues);
})
}
async.parallel([getPosts, getVenues], function(err, results) {
if(err) {
next(err);
}
res.send(results.sort(function(a, b) {
//if default sorting is not enough you can change it here
return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
}));
});
This code assumes you are inside an express route and that both Posts and Venues have a common attribute; date. In case you named these dates attributes differently you would have to improve the sort algorithm.

How can I pass parameters to a view using cradle (CouchDB)

Using cradle, how am I able to pass parameters to a view in CouchDB?
Update
Say I want to return documents which match other properties than _key (the default)...
// document format
{
_key,
postHeading,
postBody,
postDate
}
What if I wanted to match documents against the postHeading property... How would I go about this? What would the view look like, and how would I pass a search string to that view?
At the moment I'm doing this...
database.get("980f2ba66d5c8f9c91b9204a4d00022a", function (error, document)
{
});
I would like to access a view instead, and instead of the 40 character long auto-generated key, I'd like to pass a string, matching another property.
Something along the lines of this...
database.save("_design/posts", {
single: {
map: function (document)
{
if (document.postHeading == PARAMETER_PASSED_GOES_HERE)
emit(null, document);
}
}
});
database.view("posts/single", function (error, documents)
{
});
If you are querying a view try to pass second parameter as options object with your settings, for example:
db.view('characters/all', {descending: true}, function (err, res) {
res.forEach(function (row) {
sys.puts(row.name + " is on the " +
row.force + " side of the force.");
});
});
Also be aware of this:
Some query string parameters' values
have to be JSON-encoded.
EDIT:
As far as I know you can't create a view in CouchDB where you pass your custom parameter which will be used in map/reduce function code. You have to emit keys from your map function and based on them you can query the view with parameters like startkey and endkey. Try to look at Database Queries the CouchDB Way article.
db.get('vader', function (err, doc) {
doc.name; // 'Darth Vader'
assert.equal(doc.force, 'dark');
});
It looks like the searched value (parameter) here is 'dark' out of all force keys?
Cradle is also able to fetch multiple
documents if you have a list of ids,
just pass an array to get:
db.get(['luke', 'vader'], function
(err, doc) { ... });

Resources