Mongodb - Search by id and embedded array value - javascript

Im trying to write a function that will search for an object by ID and whether or not a value is contained in an embedded array within the object.
{
"_id" : ObjectId("569bea91c0e1fee4063527ac"),
"user" : ObjectId("568c65174fee132c36e199dd"),
"votes" : 9,
"image" : "./modules/deals/client/img/uploads/1546f914dba7e1732ea853cd70d79148.jpg",
"price" : "12.95",
"retailer" : "argos.co.uk",
"voters" : [{
"user" : ObjectId("568c65174fee132c36e199dd"),
},
{
"user" : ObjectId("568c65174fee132c36e199dd"),
},
{
"user" : ObjectId("568c65174fee132c36e199dd"),
}]
I would like to search by the _id and the voters.user.
I believe i need to finish this function correctly
exports.dealByIdAndVoter = function(req, res) {
Deal.count({
$where: function () {
}
},
function(err, dealByIdAndVoter) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
console.log(dealByIdAndVoter);
var data = {};
data.count = dealByIdAndVoter;
res.json(data);
}
});
};

If you do not need to use the $where function, you can construct the query with the $or operator in this manner:
Deal
.find({
$or: [
// Match by _id
{ _id: req.id },
// Match by any user in the 'voters' array with a matching 'user' field.
{ 'voters.$.user': req.id }
]
})
.count(function(err, count) {
// Handle error here
res.json(count);
});

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");
}
});

Using Firebase, how can I create a query based on UID?

I created a function that adds a UID to the database along with an item's state:
changestate(item) {
var postData = {
state: "listed",
};
var user = firebase.auth().currentUser;
var uid = user.uid;
var updates = {};
updates['foods' + '/' + item.$key + '/' + 'state' + '/' + uid] = postData;
return firebase.database().ref().update(updates);
}
I want to create a query that only shows the data corresponding to that UID. In a previous query I was using:
getLists(): FirebaseListObservable<any> {
return this.db.list('/foods', {
query: {
orderByChild: 'state',
equalTo: 'listed'
}
});}
This is the structure of my database:
{
"foods" : {
"foodID1" : {
"category" : "Produce",
"foodname" : "Apples",
"state" : {
"aePQkvozV6gehP7ihjN0OWCltKu2" : {
"state" : "listed"
}
}
},
"foodID2" : {
"category" : "Dairy",
"foodname" : "Cheese",
"state" : {
"aePQkvozV6gehP7ihjN0OWCltKu2" : {
"state" : "listed"
}
}
}
}
}
What do I need to do to show the items that correspond to a signed in user's UID?
The orderByChild property can take a path. So the code then simple becomes:
getLists(): FirebaseListObservable<any> {
return this.db.list('/foods', {
query: {
orderByChild: 'state/'+firebase.auth().currentUser.uid+'/state',
equalTo: 'listed'
}
});
}
This requires that the user is signed in of course. To test the query without a signed-in user, you can use a hard-coded value:
getLists(): FirebaseListObservable<any> {
return this.db.list('/foods', {
query: {
orderByChild: 'state/aePQkvozV6gehP7ihjN0OWCltKu2/state',
equalTo: 'listed'
}
});
}

Update Data from Within a Loop

I am trying to get my nodejs controller to update the rate in the currency table.
Everything works fine in S3T / RoboMongo, but for some reason it just wont fire the update inside the nodejs controller.
Here is my currency table
{
"_id" : "USD",
"index" : NumberInt(6),
"name" : "Dollar",
"currency" : "USD",
"symbol" : "$",
"active" : true,
"default" : false,
"rate" : 0
}
{
"_id" : "EUR",
"index" : NumberInt(2),
"name" : "Euro",
"currency" : "EUR",
"symbol" : "€",
"active" : true,
"default" : false,
"rate" : 0
}
I tried both of these, works fine in S3T but not inside nodejs:
db.currency.update (
{ _id : "EUR" },
{ $set: { rate : 123 }},
{ upsert: true }
)
db.currency.updateOne (
{ _id : "EUR" },
{ $set: { rate : 123 }},
{ upsert: true }
)
Here is my nodejs code:
var mongoose = require('mongoose');
var currencyModel = require('../models/currencyModel');
var currencyTable = mongoose.model('currencyModel');
var updateRates = () => {
return new Promise((resolve, reject) => {
for (var key in data.quotes) {
var currencyID = key.substring(3);
var newRate = (data.quotes[key] * THBUSD).toFixed(5);
console.log("currencyID: " + currencyID)
console.log("newRate: " + newRate)
currencyTable.update (
{ _id: currencyID },
{ $set: { rate : newRate }},
{ upsert: true }
),function (err, data) {
if (err) {
reject(new Error('updateRates: ' + err));
};
};
};
resolve();
})};
And here is my currencyModel (which is where I think the problem is?!?)
// Currency Model
// This model is the structure containing data from the Currency table
//
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var currencySchema = new Schema({
_id: String, // Unique Currency code
index: Number, // Indes for sorting
name: String, // Currency name
symbol: String, // Currency symbol
active: Boolean, // Active True False
rate: Number // Exchange rate (multiply with THB price)
});
module.exports = mongoose.model('currencyModel', currencySchema, 'currency');
I cannot see why it wont fire the currencyTable.update from inside nodejs.
I turned debug on in mongoose, and I see all other mongodb operations in the console like Mongoose: price.findOne({ _id: 'ATL-D406' }, { fields: {} }) etc.. but I do not see this currency.update in the console, which is why I dont think its fired off to mongodb - and I cannot see the reason.
You have a "loop" that completes execution before the inner callbacks fire. Instead just use Promises all the way through and call Promise.all() to collect all the iterated Promises and resolve them:
var updaterates = () => {
return Promise.all(
Object.keys(data.quotes).map(k => {
return currencyTable.update(
{ _id: k.substring(0,3) },
{ $set: { rate : (data.quotes[k] * THBUSD).toFixed(5) }},
{ upsert: true }
).exec()
});
)
};
The returned response of Promise.all() is an array of the response objects from the updates. Also note that this is a "fast fail" operation and calls will be made in parallel.
Object.keys() returns an "array of the key names" in the specified object. .map() iterates those keys and returns an "array" of the return value for the iterator.
We use the k as the "key name" to access the wanted key from data.quotes and use the values to perform each .update() with .exec() to return a "real" Promise. The iterator returns an "array" Promise which becomes the argument to Promise.all().

how do i replace some properties returned from database in sails

So i'm trying to replace fields on the data queried from the database in sails.
async.waterfall( [
function getscores(callback) {
Score.find({course : courseId}).paginate({page : 1 , limit: 10}).populate('course')
.exec(function(err,data) {
callback(null,data);
});
}
, function addUserInfo(result,callback) {
for(var i=0; i < result.length; i++){
result[i].user = User.findOne({id : result[i].user}).exec(function(err,data) {
var temp = {
"name" : data.name,
"id" : data.id,
"user_id" : data.user_id
}
return temp;
});
}
res.json(messageGenerator(200, 'Sucecss', result));
}],function(err) {
console.log(err);
}
);
the first function 'getScores' returns the scores array but each score property only has a user id. Now in addUserInfo function, i want to be able to add the user's name to the score property.
But the above code fails to return the users inside. the user property of score is empty. i believe the response is already sent before the program gets to add the user property ( due to asyncronousness of the database adapter).
Following a brief comment chat, the following replacement for the addUserInfo function should help you achieve what you desire:
function addUserInfo(results,callback) {
async.map(results, function(result, callback) {
User.findOne({id : result.user}).exec(function(err, data) {
callback(err, Object.assign(result, {
"user": {
"name" : data.name || null,
"id" : data.id || null,
"user_id" : data.user_id || null
}
}));
});
}, function(err, output) {
return res.json(messageGenerator(200, "Success", output))
});
}
Async map allows us to asynchronously iterate over results, allowing us to amend the result by supplying the callback with the new result as the second parameter. The Final function is our final callback, that gets provided with any err's that have occured along the way and our new Array as output.

Mongoose add filter to insert in node.js

I have a array of data need to be inserted to mongodb. But the array has some data have already existed in mongodb. How to insert this array of data only the parts which not existed in mongodb. The struct is like below:
[
{
"_id" : ObjectId("551ca2b973d1124a0445f491"),
"url" : "http://ww1.sinaimg.cn/thumbnail/ddf0f092gw1eqqyykbezwg20bu06px6u.gif",
"createdAt" : ISODate("2015-04-02T02:00:25.395Z"),
},
{
"_id" : ObjectId("551ca2b973d1124a0445f492"),
"url" : "http://ww2.sinaimg.cn/thumbnail/ddf0f092jw1eqqyz3c2bfg20b4068hdz.gif",
"createdAt" : ISODate("2015-04-02T02:00:25.401Z"),
"__v" : 0
}
]
For example the first document's url has already existed in mongodb, how to add a filter or exclude it from the array and then insert it into the mongodb.
My current insert code like below:
var imgDicts = [];
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i].img;
var imgDict = {url: img, createdAt: Date.now()};
imgDicts.push(imgDict);
};
console.log(imgDicts);
Img.collection.insert(imgDicts, function(err, docs){
if (err) {
callback(err, null);
} else {
callback(null, {message: 'success'});
}
});

Categories

Resources