I'm new to using MongoDB. Currently, I am making a web application that requires some data storage. I established an HTTP server on Node.js that runs on localhost:3000. I also built a virtual development environment using Vagrant and VirtualBox. I am accessing the Mongo shell from PuTTy (if that is relevant at all). Before incorporating MongoDB, it worked fine as I was storing the data in the Node.js program memory.
This web app is an online to-do-list. The first error that I am getting is with the get route. The list of "to-do"s that I have inserted into the Mongo database would not appear on the site in localhost. It seems to not be getting the data from the database. The second error that I am getting is with the post route. When I insert a "to-do" through the user interface at localhost and I refresh the page, the to-do-list on localhost gets updated with that particular to-do (but not with the ones I inserted in the database). But, it doesn't seem to add it into the database, and I still get this error on the console:
vagrant#precise32:~/app$ node server.js
{ description: 'descTest3', tags: [ 'tagTest3' ] }
Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
I'm not sure why I got that error since I do not seem to be using any promises.
server.js
var express = require("express"), http = require("http"), app = express(), mongoose = require("mongoose");
app.use(express.static(__dirname + "/client"));
app.use(express.urlencoded());
mongoose.connect('mongodb://localhost/WatNext');//connect to the WatNext data store in mongoDB
var ToDoSchema = mongoose.Schema({
"description": String,
"tags": [ String ] //array of Strings
});
var ToDo = mongoose.model("ToDo", ToDoSchema)
http.createServer(app).listen(3000);
//get and post routes:
app.get("/toDos.json", function (req, res) {
ToDo.find({}, function (err, toDos) {
if (err != null){
console.log(err);
}
res.json(toDos);
});
});
app.post("/todos", function (req, res) {
console.log(req.body);
var addedToDo = new ToDo({"description" : req.body.description, "tags" : req.body.tags});
//save function saves object into the database
addedToDo.save(function (err, result) {
if (err != null){//if there is an error
console.log(err);
res.send("ERROR SAVING");
}
else {
ToDo.find({}, function (err, result) {
if (err != null){//if there is an error in finding
res.send("ERROR FINDING");
}
res.json(result);
});
}
});
});
app.js
var main = function (toDoObjects) {
//do stuff with ToDoObjects including outputting the list of ToDos
};
$(document).ready(function() {
$.getJSON("toDos.json", function(toDoObjects) {
main(toDoObjects);
})
});
mongo shell
> show dbs
WatNext 0.0625GB
local 0.03125GB
> use WatNext
switched to db WatNext
> show collections;
system.indexes
toDoCollection
todos
> db.toDoCollection.find();
{ "_id" : ObjectId("58b38dd8fb355f57162d9cf1"), "description" : "Get groceries and eat afterwards", "tags" : [ "shopping", "chores" ] }
{ "_id" : ObjectId("58b38dd8fb355f57162d9cf2"), "description" : "Make up some new To-Dos", "tags" : [ "writing", "work" ] }
{ "_id" : ObjectId("58b38dd8fb355f57162d9cf3"), "description" : "Prep for Monday's class", "tags" : [ "work", "teaching" ] }
{ "_id" : ObjectId("58b38dd8fb355f57162d9cf4"), "description" : "Answer emails", "tags" : [ "work" ] }
{ "_id" : ObjectId("58b38dd8fb355f57162d9cf5"), "description" : "Take April to the park", "tags" : [ "chores", "pets" ] }
{ "_id" : ObjectId("58b38dd8fb355f57162d9cf6"), "description" : "Finish writing this book", "tags" : [ "writing", "work" ] }
EDIT:
I found out it was just an error of naming.
I also found out that
mongoose.Promise = require("bluebird");
solved the problem with the promise error. Remember to install the module first though:
npm install --save bluebird
I found out what was wrong. It was an error in naming for the GET and POST routes. It should have been:
app.get("/todos.json", function (req, res) { //get the data from the collection called 'todos' in MongoDB
as well as:
$.getJSON("todos.json", function(toDoObjects) {
I should have used the todos collection instead of toDoCollection:
"description" : "descTest1", "_id" : ObjectId("58b39a1fb1a30305075408fa"), "tags" : [ "tagTest2" ], "__v" : 0 }
{ "description" : "descTest2", "_id" : ObjectId("58b4c837d47a5604c7c0609a"), "tags" : [ "tagsTest2" ], "__v" : 0 }
{ "description" : "descTest3", "_id" : ObjectId("58b4ca0491f4c804d200cda9"), "tags" : [ "tagTest3" ], "__v" : 0 }
{ "description" : "descTest4", "_id" : ObjectId("58b4e636b71d0a05ebb7a71a"), "tags" : [ "tagTest4" ], "__v" : 0 }
{ "description" : "descTest5", "_id" : ObjectId("58b60211428520053a4714ed"), "tags" : [ "tagTest5" ], "__v" : 0 }
{ "_id" : ObjectId("58b6037839e65d96e13cf68e"), "description" : "descTestMONGO", "tags" : [ "tagTestMONGO" ] }
{ "_id" : ObjectId("58b605b339e65d96e13cf690"), "description" : "Take April to the park", "tags" : [ "chores", "pets" ] }
Related
There is such a document structure in MongoDB
{
"_id" : ObjectId("58f7d556aa52ce456672a67e"),
"created" : ISODate("2017-04-19T21:23:34.315Z"),
"context_task" : [
{
"task" : "some text ",
"status" : false,
"_id" : ObjectId("58f7d559aa52ce456672a67f")
}
],
"head" : {
"userID" : "58f48037fc894e19a3f7b81b",
"head_task" : "test record "
},
"__v" : 0
}
I add data to the context_task.task using the following query:
task.findOneAndUpdate({"_id": req.body.id_project},
{$push: {'context_task': {'task': req.body.input_task,'status': false}}},{new: true},
function (err, doc) {
if (err) return next(err);
var body = req.body.id_project+","+req.body.input_task;
console.log(doc);
res.status(200).send(body);
});
Tell me, how can I get the context_task._id of a new record after inserting it? In this case, the entire document is returned.
Every mongo document is associated with a default _id, in case not provided it will be ObjectId.
In case you want to use _id value for any other purpose, why don't you have your own _id value, which has to be unique throughout collection. The value can be of any datatype as well as nested also.
I am trying to make a list of username and passwords so that when a user signs in with their credentials they can see all the data that everyone else sees but they still have to use their own credential. I wanted to make a list of objects like this users : [{username : "user1", password : "pass1"}, {username : "user2", password : "pass2"}]. this should be created on signup. I though subdocs would help but I'm not getting what I want. I have this:
var userlist = new mongoose.Schema({username: String, password : String })
var userSchema = new mongoose.Schema({
users : [userlist]
})
and I attempted to add the new users to the array like this:
app.post("/signup", function(req, res){
var user = new User;
user.users.push({username : req.body.username, password : req.body.password})
user.save(function(err){
if(err) return handleError(err);
console.log("success")
})
// User.create(users : [{username : req.body.username, password : req.body.password}], function(err, doc){
// console.log(doc);
// })
res.redirect("/login")
})
this givs me this
> db.users.find().pretty()
{
"_id" : ObjectId("56ba6219763de71c03199a70"),
"users" : [
{
"username" : "user1",
"password" : "pass1",
"_id" : ObjectId("56ba6219763de71c03199a71")
}
],
"__v" : 0
}
{
"_id" : ObjectId("56ba6225763de71c03199a72"),
"users" : [
{
"username" : "user2",
"password" : "pass2",
"_id" : ObjectId("56ba6225763de71c03199a73")
}
],
"__v" : 0
}
>
It's making separate documents. I want it to look like this
{
"_id" : ObjectId("56ba6219763de71c03199a70"),
"users" : [
{
"username" : "user1",
"password" : "pass1",
"_id" : ObjectId("56ba6219763de71c03199a71")
},
{
"username" : "user2",
"password" : "pass2",
"_id" : ObjectId("56ba6225763de71c03199a73")
}
],
"__v" : 0
}
Having the objectIDs in the subdocs are not so important to me . I just want to group all the users together so that when they go to login I could do something like if the doc is there the credentials are good so continue to other parts of website.
I am not sure if you have resolved you question by now or not, regardless here is the answer to your problem.
Firstly if you don't need _id in subdocument then state that in the schema accordingly and no _id will be created.
var userSchema = new Schema({ username: String, password: String},{ _id: false });
If you use the above schema for user then there should be no _id field in the subdocument.
You should know that to insert a subdocument you need to know the parent for it. If you don't provide the parent while inserting the subdocument then for each insert a new parent is created. In this case parent contains _id and users subdocument. If I have the exact problem, I would go about solving it the following way:
The schema designs remain the same as shown below (I named them differently to avoid confusion):
var userSchema = new Schema({username: String, password: String},{ _id : false });
var userListSchema = new Schema({
users: [userSchema]
});
Now I will declare the parent model as follow:
var UserList = mongoose.model('UserList', userListSchema);
//see below what list gets assigned.
var list;
Now let's assume I have a route handler where I would like to keep adding the users upon sign up something as shown below:
app.get("/newuser/:username/:password", function(req, res) {
//create user model
var User = mongoose.model('User', userSchema);
//load user module, for testing i use params, you can change this to req.body
var user = new User({username: req.params.username, password: req.params.password});
//I would like to find the first document in userlists collection
UserList.findOne({}, function(err, result) {
if(err) console.log(err);
//below if condition is true, if there is one document with users subdoc
if(result) {
console.log('Found existing document with users subdocument. Adding user to array.')
//assign the parent where the subdoc should be inserted to list
list = result;
//there already is a document with subdocument users, so append to it
list.users.push(user);
//save the changed list.
list.save(function(err) {
if (err) console.log(err);
console.log('User saved.');
});
} else {
console.log('No document found. Creating one and adding this user to users subdocument.');
// initialize list model with first ever user
list = new UserList({ users: [user] });
//save the new changed list
list.save(function(err) {
if (err) console.log(err);
console.log('User saved.');
});
}
})
});
Done. Now when I run the app and access the following URL for the first time
http://127.0.0.1:8080/newuser/user1/pass1
The userslist collection would look as follow:
> db.userlists.find().pretty();
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
}
],
"__v" : 0
}
I would like to access the link with different params as shown below:
http://127.0.0.1:8080/newuser/user2/pass2
And the output of the collection looks as follow:
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
},
{
"password" : "pass2",
"username" : "user2"
}
],
"__v" : 1
}
Now I terminate the app and then re-run the app and access the following url:
http://127.0.0.1:8080/newuser/user7/pass7
And the output of the collection looks as follow:
{
"_id" : ObjectId("56c349d6479f5b9b1eaea1c8"),
"users" : [
{
"password" : "pass1",
"username" : "user1"
},
{
"password" : "pass2",
"username" : "user2"
},
{
"password" : "pass7",
"username" : "user7"
}
],
"__v" : 2
}
There you go. I feel bad to see that userlists collection would always always always have one document and its array would keep expanding, maybe not a good practice to solve your issue in this manner. If I were you, I would store each user as a single record and then do the group by or any other aggregation operation.
I have a Mongodb database with resume objects like below. I am using a node-express server. And I am querying the mongo database to get objects based on a specific skill. For example: If I query for a skill: jquery, only objects with that skill is returned. The problem is with the get function that is returning objects from the database.
In the highlighted code: If I directly insert the object like:
Resume.find({skills.jQuery : 2},function(err, results){...}
then I get the expected results.
However if I insert it dynamically (skillSet), then it doesnot work. Iit checked the value for skillSet and it give me what I expect('skills.JQuery')
var skillSet = ("'"+'skills.' + req.params.skill +"'");
console.log('skillSet',skillSet) //'skills.jQuery'
Resume.find({skillSet : 2},function(err, results){
Below is the code snippet:
{
"_id" : ObjectId("56031b4353b32084651173fb"),
"uuid" : "acd06792-87c3-4b0e-827a-8bd19d7f9c03",
"creationDate" : ISODate("2015-09-23T21:36:03.728Z"),
"status" : "3",
"name" : "resume_dev",
"__v" : 0,
"skills" : {
"node" : 2,
"react" : 2,
"React" : 3,
"JQUERY" : 2,
"JavaScript" : 15,
"JQuery" : 5,
"Backbone" : 3,
"Node" : 2,
"Angular" : 4,
"Javascript" : 2,
"jQuery" : 17,
"javascript" : 3
}
}
router.get('/skills/:skill', function(req, res){
console.log("req.params.skill",req.params.skill);
var skillSet = ("'"+'skills.' + req.params.skill +"'");
console.log('skillSet',skillSet) //skills.react
Resume.find({skillSet : 2},function(err, results){
console.log('hi');
console.log(skillSet)
console.log(results);
if (err) {
res.status(500).json(err);
}
else {
// console.log("====>",results);
res.status(200).json(results);
// res.render('status',{Resume: JSON.stringify(results)});
}
});
});
When I understand your question correctly, you can do something like this:
var query = {};
query['skills.' + req.params.skill] = 2;
Resume.find(query,function(err, results){
// Do something with the callback
};
EDIT:
If you want to get all numbers greater or equal to 1, you will need $gte. Here are the docs. This is the updated query:
var query = {};
query['skills.' + req.params.skill] = {$gte: 1};
Resume.find(query,function(err, results){
// Do something with the callback
};
I'm just starting out with express, node, and MongoDB and I seem to be experiencing a bit of a problem getting data from mongo in node/express.
I have a database called testdb with a collection called tests and here is the output of tests
{
"_id" : ObjectId("5395f91ced382cec1f8d70f1"),
"name" : "CHATEAU DE SAINT COSME",
"year" : "2009",
"grapes" : "Grenache / Syrah",
"country" : "France",
"region" : "Southern Rhone",
"description" : "The aromas of fruit and spice...",
"picture" : "saint_cosme.jpg"
}
{
"_id" : ObjectId("5395f91ced382cec1f8d70f2"),
"name" : "LAN RIOJA CRIANZA",
"year" : "2006",
"grapes" : "Tempranillo",
"country" : "Spain",
"region" : "Rioja",
"description" : "A resurgence of interest in boutique vineyards...",
"picture" : "lan_rioja.jpg"
}
in routes\index.js I have this
var express = require('express');
var router = express.Router();
var mongo = require('mongodb');
var db = new mongo.Db('testdb', new mongo.Server('localhost',27017),{auto_reconnect:true,safe:false});
var testData = db.collection('tests');
/* GET home page. */
router.get('/', function(req, res) {
testData.find().toArray(function(e,doc){
if(e){
throw e;
}
console.log(doc);
});
res.render('index', { title: 'Express' ,docs:"is jade cool?"});
});
module.exports = router;
as it stands the toArray callback doesn't seem to get called (console.log is not executed and no error is thrown).
if I place res.render in the toArray callback my app hangs in the browser.
since this is my first express app I'm sure I'm making a noob mistake.
I know toArray is async, but it should have been called eventually (and a console log or error should have shown in the terminal)
does anyone know why toArray is not working?
I am trying to create a shotgun npm command for deleting all topics ever created by a user
This is a sample user entry (users are stored in a collection called 'users'):
{
"__v" : 0,
"_id" : ObjectId("536c4c8fafec055606f01840"), //the id I want to store to a variable and use the variable to find all topics with that id in the 'creator' document
"joinDate" : ISODate("2014-05-09T18:13:28.079Z"),
"lastActiveDate" : ISODate("2014-05-09T18:13:48.918Z"),
"lastSocketId" : null,
"password" : "Johndoe6",
"roles" : [],
"username" : "johndoe6"
}
This is a sample topic entry (topics are stored in a collection called 'topics'):
{
"__v" : 4,
"_id" : 202, //unreliable as these change all the time
"body" : "example topic text",
"commentCount" : 0,
"creator" : ObjectId("536c4c8fafec055606f01840"), //this is the id I want to be found with my variable from a found user
"date" : ISODate("2014-05-14T13:58:13.668Z"),
"editedBy" : ObjectId("536f0392ca01fb0e39364c02"),
"editedDate" : ISODate("2014-05-14T13:59:27.607Z"),
"lastCommentDate" : ISODate("2014-05-14T13:58:13.670Z"),
"tags" : [],
"title" : "test",
"views" : [],
}
Here is a snippet of my code:
exports.invoke = function (shell, options) {
if (!options.confirm) {
shell.warn("Are you sure you want to delete all topics made by {{0}}? (Y/N)".format(options.username));
return shell.setPrompt('confirm', 'purgeTopic', options, 'Are you sure?');
}
shell.db.User.findOne({ username: options.username }, function (err, user) {
var userid = something //this is where I want it to pluck out the user's ID and store it for later
if (err) return shell.error(err);
if (!user) return shell.error("No user {{0}} exists.".format(options.username));
//otherwise
shell.db.Topic.where('creator').equals(userid).remove(function (err) {
As you can see, options.username is a variable that has been typed in by the user doing the command. On the last line I want it to remove topics that have a subdocument 'creator' with the id of the 'user'. How can this be accomplished?
It would simply be:
var userid = user._id;
But you'd want to put that after your if (!user) check in case user is null.