How to update mongoDB from post() - angularjs

I am creating a MEAN Stack application. My post function is as follows:
app.post('/updateGroup/:id', function(req, res) {
var id = req.params.id; // = mongoDB ObjectID ie: "55616e2a37e8728266ceac6"
var vals = {};
vals['hostName'] = req.body.hostName // = a String ie, "Steve"
// this is a different name value than the
// current hostName key that is in
// the groupList db
db.groupList.update(
{"_id": id},
{$set : vals},
function(err, result) {
if (err) {
console.log(err);
}
else {
console.log(result);
}
}
);
});
When I access this function in my front-end Angular code my
console.log(result);
Comes out as:
{ ok: true, n: 0, updatedExisting: true }
But I should see n: 1 to indicate there was an update? Why is my Node application not updating my mongoDB key:value pair?
Is there something about db.collection.update() that I'm missing?

I was able to figure it out:
When assigning the _id query I needed to do it like this:
id['_id'] = mongojs.ObjectId(req.params.id);

Related

How to get all subcollection documents with subcollection name as a date? [duplicate]

Say I have this minimal database stored in Cloud Firestore. How could I retrieve the names of subCollection1 and subCollection2?
rootCollection {
aDocument: {
someField: { value: 1 },
anotherField: { value: 2 }
subCollection1: ...,
subCollection2: ...,
}
}
I would expect to be able to just read the ids off of aDocument, but only the fields show up when I get() the document.
rootRef.doc('aDocument').get()
.then(doc =>
// only logs [ "someField", "anotherField" ], no collections
console.log( Object.keys(doc.data()) )
)
It is not currently supported to get a list of (sub)collections from Firestore in the client SDKs (Web, iOS, Android).
In server-side SDKs this functionality does exist. For example, in Node.js you'll be after the ListCollectionIds method:
var firestore = require('firestore.v1beta1');
var client = firestore.v1beta1({
// optional auth parameters.
});
// Iterate over all elements.
var formattedParent = client.anyPathPath("[PROJECT]", "[DATABASE]", "[DOCUMENT]", "[ANY_PATH]");
client.listCollectionIds({parent: formattedParent}).then(function(responses) {
var resources = responses[0];
for (var i = 0; i < resources.length; ++i) {
// doThingsWith(resources[i])
}
})
.catch(function(err) {
console.error(err);
});
It seems like they have added a method called getCollections() to Node.js:
firestore.doc(`/myCollection/myDocument`).getCollections().then(collections => {
for (let collection of collections) {
console.log(`Found collection with id: ${collection.id}`);
}
});
This example prints out all subcollections of the document at /myCollection/myDocument
Isn't this detailed in the documentation?
/**
* Delete a collection, in batches of batchSize. Note that this does
* not recursively delete subcollections of documents in the collection
*/
function deleteCollection(db, collectionRef, batchSize) {
var query = collectionRef.orderBy('__name__').limit(batchSize);
return new Promise(function(resolve, reject) {
deleteQueryBatch(db, query, batchSize, resolve, reject);
});
}
function deleteQueryBatch(db, query, batchSize, resolve, reject) {
query.get()
.then((snapshot) => {
// When there are no documents left, we are done
if (snapshot.size == 0) {
return 0;
}
// Delete documents in a batch
var batch = db.batch();
snapshot.docs.forEach(function(doc) {
batch.delete(doc.ref);
});
return batch.commit().then(function() {
return snapshot.size;
});
}).then(function(numDeleted) {
if (numDeleted <= batchSize) {
resolve();
return;
}
// Recurse on the next process tick, to avoid
// exploding the stack.
process.nextTick(function() {
deleteQueryBatch(db, query, batchSize, resolve, reject);
});
})
.catch(reject);
}
This answer is in the docs
Sadly the docs aren't clear what you import.
Based on the docs, my code ended up looking like this:
import admin, { firestore } from 'firebase-admin'
let collections: string[] = null
const adminRef: firestore.DocumentReference<any> = admin.firestore().doc(path)
const collectionRefs: firestore.CollectionReference[] = await adminRef.listCollections()
collections = collectionRefs.map((collectionRef: firestore.CollectionReference) => collectionRef.id)
This is of course Node.js server side code. As per the docs, this cannot be done on the client.

Mongoose stops to $push to array if the field already exists in a document

I am using Node and Mongoose, and trying to set an array of ISODate elements:
"visitLog" : [
ISODate("2017-10-22T22:43:49.571Z"),
ISODate("2017-10-22T22:44:39.572Z"),
ISODate("2017-10-22T23:35:36.111Z"),
ISODate("2017-10-22T23:48:26.516Z"),
ISODate("2017-10-22T23:50:33.378Z"),
ISODate("2017-10-22T23:53:56.227Z"),
ISODate("2017-10-22T23:57:20.986Z")
]
So I had an existing schema where visitLog field did not existed, added new field to a schema - visitLog: [ {type: Date, default: '' }],and it worked - the result is what you see above.
But when I created a new document with updated schema that already has an empty array in it - "visitLog" : [ ] , $push just stopped working.
Here is mongoose query, if needed:
// conditions is a ternary operator that checks whether req.body username
// is an email or not, and puts needed condition to a query
var conditions = (!/^[a-zA-Z0-9\-\_\.\+]+#[a-zA-Z0-9\-\_\.]+\.[a-zA-Z0-9\-\_]+$/.test(req.body.username)) ? ' {email: req.body.username } ' : ' {username: req.body.username } ';
var fieldsToSet = {
$push: {
visitLog: new Date().toISOString(),
}
};
var options = { upsert: true };
User.findOneAndUpdate(conditions, fieldsToSet, options, function(err, user) { ...
The working document was created in mongo console, while the second was generated on a server, but I can't how can this make any difference.
Using $push shuld work with empty arrays. Can someone explain what's wrong here?
Thank you.
Edit
It figures that using findByIdAndUpdate without conditions works for both documents:
var fieldsToSet = {
$push: {
visitLog: new Date().toISOString(),
}
};
var options = { new: true };
req.app.db.models.User
.findByIdAndUpdate(req.user.id, fieldsToSet, options, function(err, user) {
You can do with the following query.
User.findOne(condiitons, (err, user) => {
if (user) {
var date = new Date().toISOString();
user.visitLog.push(date);
user.save();
...
}
});

how to query mongoose with multiple query params via an object or an array?

I want to send js object to the backend or an array so that in the backend code ( below ) I can use the values and make a search in the mongodb ( using mongoose ) to get the data.
server code
exports.prioritySearch = function(req, res, next, id) {
console.log( 'prioritySearch-API id = ', id);
console.log( ' req.params = ', req.params);
// console.log( ' req = ', req);
// Property.find({ Left_VM_P : 'true' }).exec(function(err, properties) {
Property.find({ id : 'true' }).exec(function(err, properties) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(properties);
}
});
};
Angular Service that calls this api
.factory('prioritySearchSvc', function($q, _, $http, currentUrl, TodayDateSvc) {
console.log('186-S---- inside SinglePropertyDataService ');
var Priority = 'Left_VM_P';
var deferred = $q.defer(),
url = currentUrl+"/api/prioritySearch/"+Priority;
This below code works but next one don't which I dont understand why.
// below query works
Property.find({ Left_VM_P : 'true' }).exec(function(err, properties) {
// but i want below query to work coz i want to change the id parameter so I can modify each time what key is searched for, here id = Left_VM_P but why isn't it working..
Property.find({id : 'true' }).exec(function(err, properties) {

CloudantDB & NodeJS: Query data with specific id

I just created a NodeJS cloudantDB web starter on bluemix. Then, I have a API get data from cloudantDB and get successfull but it returns all data. Please see js file:
js file:
app.get('/api/provider', function(request, response) {
console.log("Get method invoked.. ")
db = cloudant.use(dbCredentials.dbProvider);
var docList = [];
var i = 0;
db.list(function(err, body) {
if (!err) {
var len = body.rows.length;
console.log('total # of docs -> '+len);
if(len == 0) {
// error
} else {
body.rows.forEach(function(document) {
db.get(document.id, { revs_info: true }, function(err, doc) {
if (!err) {
if(doc['_attachments']) {
// todo
} else {
var responseData = createResponseDataProvider(
doc._id,
doc.provider_type,
doc.name,
doc.phone,
doc.mobile,
doc.email,
doc.logo,
doc.address
);
}
docList.push(responseData);
i++;
if(i >= len) {
response.write(JSON.stringify(docList));
console.log('ending response...');
response.end();
}
} else {
console.log(err);
}
});
});
}
} else {
console.log(err);
}
});
If I want to add parameter to API to get specific data from DB , Do we need create search index or query on cloudant, afer that call API the same : app.get('/api/provider/:id'). Please help me review and sharing. Thanks
you could get the document by id/name:
db.get(docID, function(err, data) {
// do something
});
references:
https://github.com/apache/couchdb-nano#document-functions
https://github.com/cloudant/nodejs-cloudant#api-reference
You can use a search function of Cloudant.
You need to create search index. In search index you can manage what data you want to get.
Example: https://cloudant.com/for-developers/search/
Following this code after create search index.
...
var query = {q: "id:doc.id"};
db.search('design document name', 'index name', query, function(er, result) {
if (er) {
throw er;
}
console.log(result);
});

Output all documents in mongoose

I am using mongoose ODM and have a schema which looks like this:
var banSchema = new Schema({
userid: { type: String, required: true, unique: true },
name: String,
groupid: String,
reason: String,
timestamp: Date
});
I want to output every single user id from all documents in the collection. I am using this query to obtain the userid objects. However I cannot seem to get the full list automatically. I have to manually enter the object number as seeen below:
bot.onText(/\/sync/i, function (msg) {
var fromId = msg.from.id;
var chatId = msg.chat.id;
if (fromId == config.sudo) {
console.log('Sudo Confirmed And Authorized!');
Ban.find({}, function (err, obj) {
console.log(obj[0].userid); // Returns A Single ID
console.log(obj[1].toObject().userid); // Returns a different ID
bot.sendMessage(chatId, obj[1].toObject().useridid);
});
} else {
console.log('Someone Is Trying To Act Like Sudo! *sigh*');
bot.sendMessage(chatId, 'You Are Not A Mod!');
}
});
This however does not return a full list of id's as I want. How could I solve this issue?
The code above is for a telegram bot which on a /sync command it should return a message with all ids from the collection.
Telegram bot API Limits
Due to the API limits, the entire output should be in a single message.
var query = Ban.find({}).select({
"userid": 1,
//Add more column fields here
"_id": 0 //Ensures _id is not displayed
});
var arr = [];
query.exec(function (err, results) {
if (err) throw err;
results.forEach(function (result) {
arr.push(result.userid);
// Add more column fields here;
});
var fixedJoin =arr.join("\n");
console.log(fixed);
bot.sendMessage(chatId, 'List\n\n' + fixedJoin);
});
The easiest way to get all values of a particular field across all docs in the collection is to use distinct:
Ban.distinct('userid', function (err, userids) {
// userids is an array containing all userid values in the collection.
// string.join into a single string for the message.
bot.sendMessage(chatId, 'USER IDs\n\n' + userids.join('\n'));
});
Use this syntax
Ban.find({}).
select('userid').
exec(function(err, result) {
//result is array of userid of all document
});
You can use this syntax:
Ban.find({}, 'userid', function(err, users) {
users.forEach(function(user) {
console.log(user);
bot.sendMessage(chatId, 'users \n' + user);
});
})

Resources