How to write query.equalTo multiple times in If condition (Parse) - javascript

I am just trying to check if user_id and comment_id is there in my database table and if they exists, then do x operation or else y operation.
And, I am taking this user_id and comment_id at the runtime from the user.
So how should I write my if condition using query.equalTo so that I can do my respective operations.
Below is the code of what I am trying to do.
Parse.Cloud.define("voteForComment", function(request, response)
{
var insertVote = Parse.Object.extend("trans_Votes");
var vote = new insertVote();
var query = new Parse.Query("trans_Votes");
if(query.equalTo("user_id",
{
__type: "Pointer",
className: "_User",
objectId: request.params.user_id
})) && (query.equalTo("comment_id",
{ __type: "Pointer",
className: "mst_Comment",
objectId: request.params.comment_id
})); // how to write this two equalTo queries..(its showing error)
{
query.find
({
success : function(rec)
{
X operation here
},
error : function(error)
{
response.error(error);
`}
});
}
else
{
y operation here
}
Thanks.

Your parentheses are a bit of a mess. Removing the equalTo() function calls from the if statement leaves us with this code wireframe:
if (...) && (...);
{
...
} else {
...
}
This is not going to work because of the syntax errors. We need to change it a bit:
if ((...) && (...))
{
...
} else {
...
}
Applying these changes to your code results in this:
if (query.equalTo("user_id", {
__type: "Pointer",
className: "_User",
objectId: request.params.user_id
}) && query.equalTo("comment_id", {
__type: "Pointer",
className: "mst_Comment",
objectId: request.params.comment_id
})) {
query.find({
success: function(rec) {
X operation here
},
error: function(error) {
response.error(error);
}
});
} else {
y operation here
}
That should work.

Related

mongoose/javascript: Can't update collection in Mongodb

This is my db schema
let couponId = Schema({
RestaurantId: { type: String },
RestaurantName: { type: String },
RestaurantLocation: { type: String },
AssignedTo: Schema.Types.Mixed,
CouponValue: { type: [String] }
});
I want to update the AssignedTo field with a value of array of objects with a dynamic key and a value. I am performing this query
CouponId.findOne({
"RestaurantId": resId
}, (err, restaurant) => {
value.push({
[userNumber]: restaurant.CouponValue[0]
});
console.log(value);
restaurant.update({
"RestaurantId": resId
}, {
$set: {
"AssignedTo": value
}
}, function(err) {
if (err) {
console.log(err);
} else {
console.log("updated");
}
});
});
The query, when executed, is giving the result of updated in console but its not getting updated in db. If this query is converted to MongoShell query and executed, it gives the result and collection is getting updated, where mongoShell query i am running is
db.couponids.update({"RestaurantId" : "1234"},{$set:{"AssignedTo":[{"1234":"2345"}]}});
Where am i going wrong?
restaurant is the output from the first collection and doesn't have any update function in it... So, You need to keep the same collection name from which you have done findOne
CouponId.update({
"RestaurantId": resId
}, {
$set: {
"AssignedTo": value
}
}, function(err) {
if (err) {
console.log(err);
} else {
console.log("updated");
}
});

How to append a data to an object property in mongodb

I want to send request to a mongodb database.
For example I have this object:
{
id:"1",
requestType : {
"api1" : {count:12,firstTime:12},
"api2" : {count:6,firstTime:18}
}
}
after getting data by "id" I want to append another row to "requestType" for example "api3":{count:56,firstTime:11}.
my expected object is:
{
id:"1",
requestType : {
"api1" : {count:12,firstTime:12},
"api2" : {count:6,firstTime:18},
"api3":{count:56,firstTime:11}
}
}
currently I'm using this query by mongoose:
apiAttemptsModel.findOneAndUpdate(query, {
$set: {
requestType : {"api3":{count:56,firstTime:11}}
}
}, {upsert: true, new: true}, function (err, row) {
if (err) {
callback('err is ' + err)
} else {
callback(row);
}
});
But this code will exchange old requestType object with the new one.
Try this:
apiAttemptsModel.findOneAndUpdate(query, {
$set: {
"requestType.api3" : {count:56, firstTime:11}
}
}, {upsert: true, new: true}, function (err, row) {
if (err) {
callback('err is ' + err)
} else {
callback(row);
}
});
By the way, this is not the proper way to use callbacks.
callbacks in node are usually called with the following signature:
function(error, data) -
thus when calling callback(row); a user of this method might expect an error there, much like you did with the callback function on line 5.
The first argument is usually null when no error has occurred.
In addition, calling callback('err is ' + err) will only keep the error's message and discard its stack trace, because the error is "converted" to a string.
I'd convert your code to:
apiAttemptsModel.findOneAndUpdate(query, {
$set: {
"requestType.api3" : {count:56, firstTime:11}
}
}, {upsert: true, new: true}, function (err, row) {
if (err) {
callback(err)
} else {
callback(null, row);
}
});
Set upset to false. This will update the document, but will not create it if it does not already exist.
https://docs.mongodb.com/manual/reference/method/db.collection.update/

JS: $addToSet or $pull depending on existing/missing value

I need to add or remove an ID from an array (target), depending if it is already existing. This is how I am doing this:
var isExisting = Articles.findOne({ _id }).target.indexOf(mID) > -1
if (isExisting === false) {
Articles.update(
{ _id },
{ $addToSet: { target: mID } }
)
} else if (isExisting === true) {
Articles.update(
{ _id },
{ $pull: { target: mID } }
)
}
Is it possible to do this in a better way - without doing if/else and min. two db operations?
Mongoose operations are asynchronous, so you need to wait for its callback to get the document.
// find the article by its ID
Articles.findById(_id, function (err, article) {
// make appropriate change depending on whether mID exist in the article's target
if (article.target.indexOf(mID) > -1)
article.target.pull(mID)
else
article.target.push(mID)
// commit the change
article.save(function (err) {
});
})
Although you are doing if/else, you are doing 2 operations.
here is my suggestion
let isExisting = Articles.findOne({ _id: _id, target : mID}) //mongo can search for mID in array of [mIDs]
let query = { _id : _id };
let update = isExisting ? { $pull: { target: mID } } : { $addToSet: { target: mID } };
Articles.update(query, update);
is it better and clearer now?

mongoose findOneAndUpdate deletes nested vars

In my express/mongoose code when I update a nested var it deletes any other nested vars in the object I didn't update?
My schema:
var MySchema = new Schema({
active: { type: Boolean, required: true, default: true },
myvar: {
useDefault: { type: Boolean, required: true },
custom: { type: String },
default: { type: String }
}
});
My express middleware update function:
var updateData = req.body;
MySchema.findOneAndUpdate({ active: true }, updateData, function(err, myschema) {
if (err) throw err;
if (!myschema) { response(403, { success:false, message: "myschema not updated." }, res); }
// success
response(200, { success:true, message: "myschema updated." }, res);
});
The record initially look like this:
{
"myvar": {
"useDefault": true,
"custom": "some custom var",
"default": "some value"
}
}
When I submit an update to say the myvar.useDefault value the record ends up like this:
{
"myvar": {
"useDefault": false
}
}
Can anyone advise how to update only the targeted var and leave any other vars as they were?
The answer was to convert the response.body object to dot notation and pass that modified object to mongoose findOneAndUpdate. Thanks to #btkostner on Gitter for the answer and his toDot function. Here is the relevant bits of code:
function(req, res) {
// convert response to dot notation so objects retain other values
var dotData = toDot(req.body, '.');
MySchema.findOneAndUpdate({ active: true }, dotData, function(err, myschema) {
...
}
// author: #btcostner
function toDot (obj, div, pre) {
if (typeof obj !== 'object') {
throw new Error('toDot requires a valid object');
}
if (pre != null) {
pre = pre + div;
} else {
pre = '';
}
var iteration = {};
Object.keys(obj).forEach(function(key) {
if (_.isPlainObject(obj[key])) {
Object.assign(iteration, _this.toDot(obj[key], div, pre + key));
} else {
iteration[pre + key] = obj[key];
}
});
return iteration;
};
NOTE: I had to convert the toDot() function to ES5 for my project, here is the original ES6 version: github.com/elementary/houston/blob/master/src/lib/helpers/dotNotation.js

Dynamically building MongoDB queries in NodeJS

I receive a POST argument that looks like this:
sort:
[
{ field: 'name', dir: 'asc', compare: '' },
{ field: 'org', dir: 'asc', compare: '' }
]
}
and I need to create a MongoDB query based on that, so it should look like:
db.collection("my_collection").find( ... ).sort({'name': 'asc', 'org': 'asc'}).toArray(...);
Anyways, keep in mind that more fields could be passed. Also, it could happen that none of those fields is passed, meaning that the query won't have .sort().
My question: How can I create dynamically a query with Node's MongoDB driver? Is there a query builder or something similar?
I've found that most cases are unique regarding passed data, so building query objects varies from project to project.
So first ideas was to create middleware for express (in my case), that would parse query arguments into objects that are valid for query.
mongo-native can use as chained options to cursor, as well as in object:
Chained:
items.find({ type: 'location' }).sort({ title: 1 }).limit(42).toArray(function(err, data) {
// ...
});
Non-chained:
items.find({ type: 'location' }, { sort: { title: 1 }, limit: 42 }).toArray(function(err, data) {
// ...
});
As you can see Non-Chained can accept everything as object, while chained returns cursor after every method and can be reused. So generally you have two options:
For Chained:
var cursor = items.find({ type: 'location' });
if (sort) {
cursor.sort(sort);
}
cursor.toArray(function(err, data) {
// ...
});
For Non-Chained:
var options = { };
if (sort) {
options.sort = sort;
}
items.find({ type: 'location' }, options).toArray(function(err, data) {
// ...
});
It is important to remember that any data from query have to be validated and parsed properly. As well if you are developing API (for example), and will decide to change the way sorting arguments are passed or will want to add new way, then making middleware (in express.js) for parsing this data - is the way to go.
Example for pagination:
function pagination(options) {
return function(req, res, next) {
var limit = options.limit ? options.limit : 0;
var skip = 0;
if (req.query.limit) {
var tmp = parseInt(req.query.limit);
if (tmp != NaN) {
limit = tmp;
}
}
if (req.query.skip) {
var tmp = parseInt(req.query.skip);
if (tmp != NaN && tmp > 0) {
skip = tmp;
}
}
if (options.max) {
limit = Math.min(limit, options.max);
}
if (options.min) {
limit = Math.max(limit, options.min);
}
req.pagination = {
limit: limit,
skip: skip
};
next();
}
}
Usage:
app.get('/items', pagination({
limit: 8, // by default will return up to 8 items
min: 1, // minimum 1
max: 64 // maximum 64
}), function(req, res, next) {
var options = {
limit: req.pagination.limit,
skip: req.pagination.limit
};
items.find({ }, options).toArray(function(err, data) {
if (!err) {
res.json(data);
} else {
next(err);
}
});
});
And url examples:
http://example.com/items
http://example.com/items?skip=64
http://example.com/items?skip=256&limit=32
So it is the way to develop well flexible framework, which does not creates any rules of how things have to be coded as well as solving your challenge.

Categories

Resources