Not able to update model in loopback - javascript

I am using updatingAll method in loopback but it is not working I am not able to understand the reason
I have written something like this
let data = {
isActive: false
};
myModel
.updateAll(data, {
id: {
inq: questionIds
},
});

The order of parameters in updateAll seems to be incorrect. From documentation:
PersistedModel.updateAll([where], data, callback)
Also, it seems a callback function is required.
Callback function called with (err, info) arguments. Required.
So your call should look like this:
let data = {
isActive: false
};
myModel.updateAll({
id: {
inq: questionIds
},
}, data, (err, info) => null); //might want to add error checking to callback function

Related

How to specify function to use using an object in JS

I am trying to build a function that allows users to retrieve data from the database, but in a dynamic way. So allowing them to specify the source table, as well as which columns they would like to retrieve.
I have already built out the part that allows them to choose the table and columns, and these users only have access to data we are happy for them to retrieve.
I want this to be as dynamic as possible, so I am building a function to help me with this. I have run into one problem though so far. I have this function:
const modelMap = (model, action, criteria, options) => {
const models = {
EXTERNAL_USER: {
READ: services.externalUser.readExternalUser(criteria, options),
},
TASK: {
READ: services.task.readTask(criteria, options),
},
USER: {
READ: services.user.readUser(criteria, options),
},
}
return models[model][action]
}
So, for example, I call this function using
modelMap('EXTERNAL_USER', 'READ', { id: userID }, { populates: ['documents'] }).
This returns the data I want, however I get an ``OperationError` in my terminal:
OperationalError [UsageError]: Invalid populate(s).
Details:
Could not populate `documents`. There is no attribute named `documents` defined in this model.
The error is saying that the Task model has no attribute documents, which it doesn't. So I am guessing that even though I am not trying to access the readTask function, it is being called anyway. How can I get around this?
SOLUTION
I altered the models object to the following:
const models = {
EXTERNAL_USER: {
READ: () => services.externalUser.readExternalUsers(criteria, options),
},
TASK: {
READ: () => services.task.readTask(criteria, options),
},
USER: {
READ: () => services.user.readUser(criteria, options),
},
}
And I can then use await modelMap(model, action, criteria, options)() to get the data I need.
Yes. The functions called anyway

Why mongoose middleware "pre" remove with { query: true } is not called?

I'm a bit stuck on this problem.
I have read all the mongoose documentation about middleware and some stackoverflow issue and was unable to find-out how to solve my problem without duplicating queries (find then remove).
Normally, pre middleware on remove will not fire when call from Model and not from document. But according with the doc, if I add {query: true}, my function will be called from model query.
I use the latest monngoose version (5.4.16)
Here is my code.
let mySchema= new mongoose.Schema({
name: String,
comment: String
}, { usePushEach: true });
mySchema.pre('remove', { document: true }, function() {
console.log('remove document');
});
mySchema.pre('remove', { query: true }, function() {
console.log('remove');
});
const MyModel = mongoose.model('MyModel', mySchema);
And the call here
MyModel.deleteOne({ _id: modelId }, (errorRm) => {
if (errorRm) {
return res.json({ success: false, message: `${errorRm.message}` });
}
return res.json({ success: true, message: 'Model successfully removed' });
});
The model is successfully removed but nothing is logged from the "pre" functions...
Any help would be welcomed.
It's because you're using MyModel.deleteOne(). Use MyModel.remove() and it will work.
Acoording to the documentation:
You can pass options to Schema.pre() and Schema.post() to switch whether Mongoose calls your remove() hook for Document.remove() or Model.remove():

AngularJS - Correctly formatting asynchronous calls

newbie here.
I am trying to understand how I need to structure asynchronous calls within my controller to fit my specific use case:
Consider the following code snippet from an Angular Module in "service.js" within my project:
function getSearchObjects(projectName, title) {
var payload = JSON.stringify({
"title": title
});
var request = $http({
method: 'post',
url: URL + '/search/' + projectName,
data: payload
});
return request.then(handleSuccess, handleError);
};
function runQuery(projectName, fromDate, toDate, sort, direction, columns) {
var from = Date.parse(fromDate);
var to = Date.parse(toDate);
var payload = JSON.stringify({
"fromDate": from,
"toDate": to,
"sort": sort,
"direction": direction,
"columns": columns
});
console.log(payload);
var request = $http({
method: 'post',
url: URL + '/query/' + projectName,
data: payload
});
return request.then(handleSuccess, handleError);
}
function handleSuccess(response) {
return response.data;
};
function handleError(response) {
if (!angular.isObject( response.data ) || !response.data.error) {
return( $q.reject( "An unknown error occurred." ) );
}
return $q.reject( response.data.error );
};
});
Within my controller, I am trying to troubleshoot the following function:
$scope.submit = function() {
var objectProperties = exportsStorageService.getSearchObjects($scope.selected.project.name, $scope.selected.search)
.then(function(result) {
exportsStorageService.runQuery($scope.selected.project.name, $scope.selected.start_date, $scope.selected.end_date, objectProperties.sort, objectProperties.direction, objectProperties.columns)
},
function(error) {
console.log(error);
});
};
getSearchObjects matches a title ($scope.selected.search) selected in my UI and grabs the following more detailed object from an API call:
{ title: 'Duplication Example',
sort: '#_traac-timestamp',
direction: 'desc',
columns: [ '#_traac-remote_ip', 'c-platform-m-distinct-id_s', '_type' ] }
I am trying to grab the properties returned from getSearchObjects and pass them along with a few user selected values from my UI to runQuery, which then returns data from a database to the user, but when I check the values passed to runQuery using the above logic in my controller, I get the following values. All of the objectProperties values I am attempting to pass to runQuery are undefined:
project_name: "Example Project"
start_date: 1499770800000
end_date: 1499943600000
sort: undefined
direction: undefined
columns: undefined
I have been trying to debug this, but I am too new to using Angular and asynchronous calls to really understand what I am doing wrong. My best guess currently is that I am calling runQuery before the values retrieved from getSearchObjects are attached to objectProperties. Either that or I am incorrectly referencing the properties within the objectProperties variable.
Could someone help me troubleshoot this issue, and better understand what I am doing wrong?
Thank you in advance for your help!
When you do this:
var objectProperties = some async function...
You are assigning the promise of the async function to the variable, not the result of it.
The result is coming in the .then, like you declared:
.then(function(result) { ... }
So, instead of objectProperties.sort, objectProperties.direction, objectProperties.columns, try using result.sort, result.direction, result.columns :)
If you are new to Promises, take a look at this simple, but great tutorial.
EDIT
Based on your comment, you are receiving, inside the response.data, the following object:
{"objectMatch": {
"title": "doc-event",
"sort": "#_traac-timestam‌​p",
"direction": "desc‌​",
"columns": [
"m-doc-‌​name_s",
"m-user_s",
"‌​m-full-action-type_s‌​",
"m-event-action-de‌​scriptor_s"
]}
}
So you have: response > data > objectMatch > properties you want.
The response.data you are extracting on your handleSuccess function:
function handleSuccess(response) {
return response.data;
};
So here, your result is response.data, containing the property objectMatch.
$scope.submit = function() {
var objectProperties = exportsStorageService.getSearchObjects($scope.selected.project.name, $scope.selected.search)
.then(function(result) {
...
},
...
If all of that is correct, you should be able to access the values you want using result.objectMatch.<sort, direction or columns>, like:
exportsStorageService.runQuery($scope.selected.project.name, $scope.selected.start_date, $scope.selected.end_date,
result.objectMatch.sort, result.objectMatch.direction, result.objectMatch.columns)

Update Knockout Observable Array from another view model

It seems to be a complicated scenario. But I would try to break down it simple.
In a viewmodel , I have an Observable Array that is bound to a dropdown.
(function () {
UserMgmt.PeopleViewModel = WebFramework.BaseViewModel.inherits({
initializeViewModel: function (options) {
this.initializeBinding(options);
},
initializeBinding: function (options) {
.......
.......
this.intGroups = ko.observableArray([]);
.......
getGroupsForSite: function (cb) {
this.setListValue('/GetGroupsForSite', { siteId: '123', startIndex: 0, maxRecordCount: 20 }, this.intGroups, cb);
},
setListValue: function (api, data, observable, cb) {
this.postDataRequest(api, data, function (err, result) { //Gets teh data from service
if (!err && result) {
observable(result.data);
if (cb) { cb(); }
}
});
},
....
)},
Now from this page a popup opens that has a different viewmodel and u can save a new group info there.
But while closing the modal popup, that previpus page's dropdown value needs to updated
with this saved value.
Can I do it via observableArray ?
So that , I can update from this new viewmodel and without reloading the whole previous page, it updates only the dropdown ?
Here is the second view model ....
UserMgmt.IntrusionGroupListViewModel = WebFramework.BaseViewModel.inherits({
initializeViewModel: function (options) {
this.initializeBinding(options);
},
initializeBinding: function (options) {
this.ErrorMessage = ko.observable("");
this.IsError = ko.observable(false);
SaveNewGroup: function () {
debugger;
//this.setListValue('/GetGroupsForSite', { siteId: '123', startIndex: 0, maxRecordCount: 20 }, this.intGroups, cb);
}
}
How can I achieve the desired functionality ?
What should be inside SaveNewGroup() for it to work ?
The code that instantiates the two viewmodels should pass either the first viewmodel or its intGroups member as one of the options to the second viewmodel. The second viewmodel then has access to what it needs. You can modify the observable array and changes will show up in the view.
If, for some reason, there is no code that knows about both viewmodels, you will need to use Postbox to communicate between the two.

node + mongo: updating a record requires a callback

So I'm listening for an event with socket.io, once that fires I'm trying to update a record to a new value.
socket.on('contentEdited', function (newContent) {
collection.update(
{ '_id' : ObjectId("5279262e74d92da751eb2b8e") },
{ $set: {
'content': newContent
}
}
), function (err, result) {
if (err) throw err;
console.log(result)
};
});
The syntax works in the shell, but throws the following error in node when the event fires:
Error: Cannot use a writeConcern without a provided callback
I tried adding an function at the end afterwards for basic error checking, but I'm not sure how to provide a callback in the way mongo expects.
Still kinda new to this, thanks
I think your problem is that the callback function needs to be inside the update function call instead of outside it. The format for the nodejs MongoDB driver can be found here: http://mongodb.github.io/node-mongodb-native/api-generated/collection.html#update
So it should look like this:
collection.update(
{ '_id' : ObjectId("5279262e74d92da751eb2b8e") },
{ $set: { 'content': newContent } },
function (err, result) {
if (err) throw err;
console.log(result);
})
Note that the parentheses has moved after the callback function.
You could also set the write concern to "unacknowledged" instead of "acknowledged."
The MongoDB concept of "Write Concerns" determines how certain you want to be that MongoDB successfully wrote to the DB. The lowest level of write concern, "Unacknowledged" just writes data to the server and doesn't wait to response. This used to be the default, but now the default is to wait for MongoDB to acknowledge the write.
You can learn more about write concerns here:
http://docs.mongodb.org/manual/core/write-concern/
To set the write concern to unacknowledged, add the option {w: 0}:
collection.update(
{ '_id' : ObjectId("5279262e74d92da751eb2b8e") },
{ $set: { 'content': newContent } },
{ w : 0 });
yes. maybe you have the wrong syntax. and this might make it even better
socket.on('contentEdited', function (newContent) {
collection.update(
{ '_id' : ObjectId("5279262e74d92da751eb2b8e") },
{ $set:
{ 'content': newContent }
},
{returnOriginal : false},
function (err, result) {
if (err) throw err;
console.log(result);
});
})

Categories