Unable to $pull from array - node.js

I have tried a lot of different ways but maybe I dont have the hang of the way mongodb needs me to query it.
this is what the doc looks like.
{
"username" : "amitverma",
"notifications" : {
"notification_add_user" : [
{
"sender" : "a",
"action" : "b",
"type" : "c",
"objectType" : "d",
"objectUrl" : "e"
}
]
},
"_id" : ObjectId("539aa673e97933e7a5000001")
}
I want to remove the object inside "notification_add_user". And these are the different ways I have tried to get it working.
db.notifications.update(
{'username': 'amitverma' },
{ $pull: {
"notifications.notification_add_user":{'sender': "a"}
}}
)
This works in console.
But the code that I have written for it doesnt get the job done.
// notificationtype is 'add_user'
removequery['notifications.notification_' + notificationtype] = { 'sender': 'a' };
co_notifications.update(
{'username': data.username},
{$pull : removequery}, function(err, docs){
console.log('remove notification callback')
console.log(err)
console.log(docs)
})
)

Using the native MongoDB driver, I have used the following query to update from a node console and it works:
>MongoClient = require('mongodb').MongoClient;
>format=require('util').format;
>MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if(err) throw err;
var collection = db.collection('notifications');
collection.count(function(err, count) {console.log(format("count = %s", count));});
collection.update(
{'username': 'amitverma'},
{$pull:{'notifications.notification_add_user':{'sender':'a'}}},{w:1},function(err){
if (err) console.warn(err.message);
else console.log('successfully updated');
})
})

db.notifications.find({'username': 'amitverma' }).forEach( function(result) {
var i;
for(i in result.notifications.notification_add_user) {
var sender = result.notifications.notification_add_user[i]['sender'];
if(sender === 'a') {
delete result.notifications.notification_add_user[i]['sender'];
}
}
db.notifications.save(result);
});
First i will get all the results where the username is equal to
'amitverma'
Then i loop through the notification_add_user array and see if sender is equal to 'a' and delete all the match results
And for last i save the changes

Related

concat followed by save in Mongoose does nothing

I'm using Mongoose 4.9.1 and MongoDB 2.2.33. I use concat since push is no longer supported, to add an element to an array of a model.
I do save, everything works but the updated object does not have the element I added to the array.
hotel.reviews.concat([{
name : req.body.name,
rating : parseInt(req.body.rating, 10),
review : req.body.review
}]);
hotel.save(function(err, hotelUpdated) {
if (err) {
console.log("Error adding review");
res
.status(500)
.json(err);
} else {
res
.status(201)
.json(hotelUpdated);
//.reviews[hotelUpdated.reviews.length - 1]
}
});
Did you tried :
const item = {
name : req.body.name,
rating : parseInt(req.body.rating, 10),
review : req.body.review
};
HotelModel.
findOneAndUpdate({ _id : hotel._id}, {$push:{reviews:item},{new : true},(err, doc) => {
if(err){
console.log("Something wrong when updating data!");
}
console.log(doc);
});

Cannot xor mongodb field from nodejs without mongoose

I'm trying to xor the field status, in a document such as this:
{
"_id" : ObjectId("58c51e1aedb6e4000410ddbf"),
"query" : "developer",
"user_id" : "1413322622039651",
"status" : 1,
"links" : [
"840673302343483394",
"840672745222483968",
"840672580717686785",
"840672427550089216",
"840582170548850688",
"840581988918669312"
],
"links_size" : 6,
"created" : ISODate("2017-03-12T10:08:26.369Z")
}
I'm using this code:
var args = {'_id': new ObjectID(queryId)};
var bit = {$bit: {'status': {xor: 1}}};
db.collection('query').update(args, bit, function(err, result) {});
The query produces no error but the field status is not changed. I think that the problem is that it interprets 1 as a double not as a integer. I tried: parseInt(1) but it also had no effect. I tried to use NumberInt(1) but got the error NumberInt is not defined.
So I can't make it work in my code; however, the equivalent query through the mongo shell works as expected:
db.query.update(
{"_id":ObjectId("58c3b98e458f0700045b1846")},
{"$bit":{"status":{"xor":NumberInt(1)}}}
)
I googled and found that NumberInt is present in the mongoose-int32 package but it requires mongoose. I don't want to add mongoose as a dependency for my project so I'm looking for another solution.
The problem comes from the status field type stored in your document
here it is
{ "status" : 1, ... }
but you should have this:
{ "status" : NumberLong(1), ... }
First, convert all status field to NumberLong using this code (run it directly in the shell)
db.query.find().forEach( function(obj) {
obj.status = new NumberLong(obj.status);
db.query.save(obj);
});
then just update your previous code like this :
const MongoClient = require('mongodb').MongoClient
const ObjectId = require('mongodb').ObjectId
const Long = require('mongodb').Long
MongoClient.connect('mongodb://localhost:27017/database', function (err, db) {
if (err != null) {
console.log(err)
} else {
let args = {'_id': new ObjectId('58c64231b13b6239d9e496da')}
let bit = {$bit: {'status': {xor: Long.fromInt(1)}}}
db.collection('query').update(args, bit, function (err, result) {
if (err != null) {
console.error(err)
}
db.close()
})
}
})
This worked using:
node v7.3.0
npm package mongodb 2.2.24
MongoDB 3.4.1

MongoDB find() won't find what I need

I am trying to find a document in a collection. I have been using this query structure on nearly all my collections, but for some reason this isnt working for this collection. Any help?
The only data in this collection right now
[ { _id: 581757143389e565b5cf8124,
companyProfileID: '86660a5b-7f61-4238-889d-1cc3087947b9',
url: 'sentsoftware.com',
appID: 1 } ]
Query Structure:
function getCompany(companyUrl, app, callback) {
MongoClient.connect(url, function(err, db) {
if (err) {
console.log(err);
} else {
console.log("We are connected");
}
var collection = db.collection('Companies');
collection.find({url: companyUrl, appID: app}).toArray(function (err, result) {
if (err) {
console.log(err);
callback(err);
} else if (result.length) {
console.log("found");
callback(result);
} else {
console.log("No document found");
callback(err);
}
});
});
}
I keep getting No document found. But if i were to take out the , appID: app part, it finds the document.
A Mongo query is type specific (although numbers can be cast), you've likely got a string where you are expecting a number.
If you ask for the string "1",
collection.find({appID: "1"})
it will only return documents with a string equal to "1", if you ask for the number 1
collection.find({appID: 1})
it will only return documents with a real number (Double, Long, Int) in.
You can check which types you have with a $type query:
collection.find( { appID : { $type : "string" } } ); // or type 2 for earlier mongo versions
collection.find( { appID : { $type : "double" } } ); // or type 1 for earlier mongo versions
collection.find( { appID : { $type : "int" } } ); // or type 16 for earlier mongo versions
Check out the BSON types and $type in the docs, currently (2016/11/11): https://docs.mongodb.com/manual/reference/operator/query/type/#op._S_type
Interestingly it will cast between Doubles, Longs and Ints; so inserting these:
db.collection("temp").insertOne({ "type" : "my double", "num" : new mongo.Double(1.0) });
db.collection("temp").insertOne({ "type" : "my long", "num" : new mongo.Long(1) });
db.collection("temp").insertOne({ "type" : "my int", "num" : 1 });
and searching for:
{ "num" : 1 }
returns the three documents.

MongoDB Upserts Variable name as a key (Node.JS)

Node.JS, MONGODB, not using Mongoose.
I have a document I'm saving. When I use UPSERT, it structures the data as so :
{ "_id" : ObjectId("573a123f55e195b227e7a78d"),
"document" :
[ {"name" : "SomeName" } ]
}
When I use INSERT it inserts it all on the root level :
{ "_id" : ObjectId("573a123f55e195b227e7a78d"), "name" : "SomeName" }
This is obviously going to lead to lots of inconsistencies. I have tried various things. I've tried various methods such as findOneAndReplace, Update with Upsert, I've tried Replace, $setOnInsert. It all does the same thing when Upsert is involved it seems.
I have tried to use document[0] to access the first block of the array, but that throws an error... 'Unexpected Token ['
I have tried various methods and dug for hours through the various documentation, and have searched high and low for someone else having this problem, but it doesn't seem to be well documented issue for anyone else.
Anyone have any recommendations to make sure that all the fields are on the ROOT level, not nested under the variable name? Relevant code below.
findReplace: function(db, document, collection) {
var dbCollection = db.collection(collection);
var filter = document.name;
return new Promise(function(resolve, reject) {
dbCollection.updateOne({
"name" : filter
}, {
document
}, {
upsert: true
}, function(err, result) {
if (err) {
console.log('error', err)
reject(err);
}
console.log("Found Document and Upserted replacement Document");
resolve([{'status' : 'success'}]);
});
});
}
When you do this:
{
document
}
You are creating an object containing a document property and the variable's value as its value:
{
document: [ {"name" : "SomeName" } ]
}
This is new functionality from ES6. If you want to access the first item of the document variable, don't create a new object:
return new Promise(function(resolve, reject) {
dbCollection.updateOne({
"name" : filter
}, document[0], { // <========
upsert: true
}, function(err, result) {
if (err) {
console.log('error', err)
reject(err);
}
console.log("Found Document and Upserted replacement Document");
resolve([{'status' : 'success'}]);
});
});

find results of attributes in mongodb are always undefined

I really really need help in this. I am using node.js with mongodb and mongoose. So far I've managed to create a schema and save those into my database.
var Bericht = new Schema({
name : String
, mail : String
, betreff : String
, inhalt : String
, datum : Date
});
var Bericht = mongoose.model('Bericht', Bericht);
I habe a html formular where I can transmit with misc. fields data, by querystring I converting those into readable strings
var bericht_data = {
name: tempo.Name
, mail: tempo.Mail
, betreff: tempo.Betreff
, inhalt: tempo.Inhalt
};
var testoro = new Bericht(bericht_data);
testoro.save(function (err) {
if (!err) console.log('Success!');
});
so tempo.Name for example is a string and it also successful in saving it.
So far I can save all data from this formular into my mongodb.
Now the very problem: I want the data back as string to handle for dynamic html.
To get the info into my console, I use
Bericht.find(
{},
{ '_id': 0},
function(err, docs) {
if (!err){
console.log(docs);
// process.exit();
}
else { throw err;}
}
);
The console gives me all data which was ever saved in my schema Bericht excluding the long _id stuff. Sample output:
[ { name: 'Hans', mail: 'hans#wurst.de', betreff: 'I lost my wurst', inhalt: 'look at me, I am amazing' } ]
That's just one, normally there would be a huge amount of data.
The idea is right now to extract only the name into a string like "Hans". I want to get this name into a var, but hell it seems impossible!
I've tried
Bericht.find(
{},
{ '_id': 0},
function(err, docs) {
if (!err){
console.log(docs.name);
// process.exit();
}
else { throw err;}
}
);
But the I get only "undefined" delivered. I appreciate your help!
Take a look at Mongoose QueryStreams. I haven't used it myself, but I've modified their example code to fit your Model, to give you an idea of how it might work in practice:
var stream = Bericht.find().stream()
, names = []
, i;
function closeHandler() {
console.log(JSON.stringify(names));
};
stream.on('data', function (doc) {
if (doc.name) {
names.push(doc.name);
}
})
stream.on('error', function (err) {
// handle err
})
stream.on('close', closeHandler)
Mongoose find return an array of documents so you should try the following:
Bericht.find(
{},
{ '_id': 0},
function(err, docs) {
if (!err){
for(var i=0; i<docs.length; i++)
{
console.log(docs[i].name);
}
// process.exit();
}
else { throw err;}
}
);

Resources