Node.js - How to create a unique id with mongoose db - node.js

I am working with Twitter authentication and want to store the twitter id as unique key in mongodb. However i see multiple entries with the same id. Here's my schema and code
Schema:
var TwitterSchema = new Schema({
accessToken: String,
accessTokenSecret: String,
name: String,
twitterId: { type: String, required: true, index: { unique: true, sparse: true } }
});
Code:
mongoose.connect('mongodb://localhost/twd')
mongoose.model('Post', TwitterSchema);
var Post = mongoose.model('Post');
var post = new Post();
post.accessToken = accessToken
post.accessTokenSecret = accessTokenSecret
post.name = twitterUserData.name
post.twitterId = twitterUserData.id
post.save(function(err){
if (err){
throw err;
promise.fail(err);
}
console.log('saved');
mongoose.disconnect();
});
promise.fulfill(post);
DB shell output
> db.posts.find();
{ "twitterId" : "21475255", "name" : "MMMK", "accessTokenSecret" : "ZYhiXMWfXvSr1aaCB93hgU243j8aapP0ALdSFlWEE", "accessToken" : "22475255-9YvKMceUInUIxcEtKAK0oMRRG2ZZxn5c52vnwPw", "_id" : ObjectId("4feddf6155203990e000001") }
{ "twitterId" : "21475255", "name" : "MMMK, "accessTokenSecret" : "ZYhiXMWfXvSr1aaCB93hgU2438aapP0ALdSFlWEE", "accessToken" : "22475255-9YvKMceUInUIxcEtKAK0oMRRG2ZZxn5c52vnwPw", "_id" : ObjectId("4feddf7b5905a1a10e000001") }

My guess is either the index isn't being created in MongoDB, or the index with the same name already exits. If it already exists, mongoose will use ensureIndex to create it, but that won't override/redefine it if it already exists. Use the mongo js shell to see if it exists, then try dropping it, restarting mongod, and running your node.js code again.
http://www.mongodb.org/display/DOCS/Indexes#Indexes-CreationOptions

Related

Mongoose MongoError : 11000

I sent a create post signal through Postman. a once time, the post signal was a successfully. but next time it was failed . error message is like this.
Error creating new record : {
"driver": true,
"name": "MongoError",
"index": 0,
"code": 11000,
"keyPattern": {
"RoutineParts.userId": 1
},
"keyValue": {
"RoutineParts.userId": null
}
}
i cant understand the error message,
my post code and user model code is like that ,
// it's post code.
router.post('/',(req,res)=>{
const newRecord = User ({
username : req.body.username,
email : req.body.email,
password : req.body.password
})
newRecord.save((err,docs)=>{
if(!err) {
res.send(docs)
}else {
console.log('Error creating new record : ' + JSON.stringify(err,undefined,2))
}
})
})
// it's user model
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema(
{
username : {type:String},
email: { type: String, required: true},
password: { type: String, required: true, trim: true },
created_at : { type: Date, default: Date.now },
updated_at : { type: Date, default: Date.now },
}
)
const User = mongoose.model('User', userSchema);
module.exports = { User }
i can't understand. In fact 'RoutineParts' is a one of model, but i didn't write user's documents. and, controller path is corrected in app.js
how can i solve it?
it's RoutineParts model
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema(
{
routine_name : {type:String},
userId : { type: String, required: true},
exercise_name : { type: String},
order : { type: Number},
}
)
const RoutineParts = mongoose.model('RoutineParts', userSchema);
module.exports = { RoutineParts }
and it's app.js contents
// Connecting data to the MongoDB through Mongoose
require('./db')
const express = require('express')
const app = express()
const PORT = 5000
const bodyParser = require('body-parser')
const userRoute = require('./controller/user')
const routineRoute = require('./controller/routine')
const RP_Route = require('./controller/routineParts')
const EX_Route = require('./controller/excersise')
app.use(bodyParser.json())
app.get("/", function (req, res) {
res.status(201).send("<h1>Hey guys! Hello World !!</h1>");
});
app.listen(PORT, function () {
console.log(`start express server on port ${PORT}`);
});
app.use('/Users', userRoute)
app.use('/Routine', routineRoute)
app.use('/Excersise', EX_Route)
app.use('/RoutineParts', RP_Route)
What's going on
I took a look at your full code. The only real problem, which also fits with the error message you are seeing, is the following :
In your ./models/routineParts.js you've set a unique field. In your case userid. E.g. if your create a new routineParts document with userid "AAA" you can not create another document with the same userid "AAA". In short this means, every user can only create 1 single routineParts document.
The first time you did a POST request to your route localhost:5000/RoutineParts it created the first routineParts document. After that, every request will fail, because it already created 1 routineParts document. ( Read here about unique index with mongoose )
See your ./controller/routineParts.js . If you try to do the same request with a different userid it should work.
How to fix
1 : Remove unique: true from your ./models/routineParts Schema.
2 : ⚡ Drop the index . Mongoose most-likey already registered this index and you have to drop it specifically. Otherwise it will always treat the userid field as unique.
3 : You are still in development, so it shouldn't hurt to also drop the RoutineParts collection.
4 : Restart the app and try to hit the POST localhost:5000/RoutineParts endpoint a couple of times. You now should be able to create multiple routineParts documents under the same user.
How to drop the index
That's a different story. This question should help you with that. They are also using mongoose. If your are using the latest version of mongoose there is a method called cleanIndexes. Use this method after you've removed the unique:true from your model.
For solve this isuse you must remove index duplicate email_1 from index menu

how to make a mongoose query to search for matching arrays

I am making a chat app where the user when first time sends a message to a person a new conversation is created in the database, But before creating a new one every time, I want to check whether the conversation exists, I'am building this in Node.js and using express framework & I'am using Mongoose to handle the database
const mongoose = require('mongoose');
const Conversation = new mongoose.Schema({
Users : [
{
user_id : {
type : String,
required : true
},
username : {
type : String,
required : true
},
name : {
type : String,
required : true
},
profileUrl : {
type : String,
required : true
}
}
],
createdAt : {
type : Date,
default : Date.now,
required : true
}
});
module.exports = mongoose.model("Conversation",Conversation);
Is there a query where I can check if there is an conversation which matches with the array I'm passing, I couldn't find a way to search for array with objects and I want all the fields to be equal not just single one
//Create a callback function on
module.exports.FindMessage= function (conditionQuery, callback) {
Users .find(conditionQuery, callback)
}
//than
User.FindMessage({$or:[{username:username}]},function(err,message){
if(err) throw err
if(message.length > 0 )
{
}
else
{
}

MongoDB and mongoose: how to add an object if it doesn't already exist

I am having some trouble with mongoDB/mongoose and node.js. I am used to SQL, and mongoDB is...hard! Here is my schema:
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
var itemSchema= mongoose.Schema({
item_info : {
user_id : Number,
location : String,
item_id : Number,
title : String
},
item_hist : {
user_id : Number,
location : String,
item_id : Number,
founddate : String
}
});
module.exports = mongoose.model('item', itemSchema);
And I can add a new item by doing this:
var item= require('./app/models/item');
var item= new item();
item.item_info.user_id = 12345;
item.item_info.location = 'This address';
item.item_info.item_id = 4444;
item.item_info.title = 'New item';
item.save(function(err)
{
if (err) throw err;
});
What I want to be able to do is say: "look for an item with item_info.item_id 5555. if it exists, do nothing. if it doesn't exist, then add it to the database." I've read through so much mongodb and mongoose documentation, but between using dot notation and accessing through nodejs instead of command line mongodb, I still can't figure out how to do this. SQL seemed so much easier!
Just use this -
var query = { user_id: 12345, location: "This address", item_id: 4444, title: "New item" },
options = { upsert: true };
Model.findOneAndUpdate(query.item_id, query, options, function(error, result) {
if (error) return;
// do something with the document
});

Mongoose returns empty while the same query in mongodb shell works fine

I know maybe this question has been asked quite many times here, I've went through several solutions people came with to similar questions but none of them seemed to help in my case.
I have two collections called users and posts and models for them look like this:
users
var mongoose = require('mongoose').set('debug', true);
var Schema = mongoose.Schema;
var usersSchema = new Schema({
name: {type: String, required: true}
});
var User = mongoose.model('user', usersSchema, 'users');
module.exports = User;
posts
var mongoose = require('mongoose').set('debug', true);
var Schema = mongoose.Schema;
var postsSchema = new Schema({
content: String,
user: {
type: Schema.ObjectId,
ref: 'users',
required: true
}
});
var Post = mongoose.model('post', postsSchema, 'posts');
module.exports = Post;
I'm trying to get the posts of a user using this code:
var Post = require('../models/posts');
...
router.get('/posts/user/:userId', function (req, res, next) {
Post.find({user: req.params.userId}, function (err, posts) {
Post.populate(posts, {path: 'user'}, function(err, posts) {
res.send(posts);
});
});
});
Mongoose debug mode reports that the following query is executed during the request:
posts.find({ user: ObjectId("592e65765ba8a1f70c1eb0bd") }, { fields: {} })
which works perfectly fine in mongodb shell (I'm using Mongoclient) but with Mongoose this query returns an empty array.
The query I run in mongodb shell:
db.posts.find({ user: "592e65765ba8a1f70c1eb0bd" })
The results I get:
{ "_id" : ObjectId("592e66b48f60c03c1ee06445"), "content" : "Test post 3", "user" : "592e65765ba8a1f70c1eb0bd" }
{ "_id" : ObjectId("592e66b98f60c03c1ee06446"), "content" : "Test post 4", "user" : "592e65765ba8a1f70c1eb0bd" }
{ "_id" : ObjectId("592e66bb8f60c03c1ee06447"), "content" : "Test post 5", "user" : "592e65765ba8a1f70c1eb0bd" }
I'm at the very beginning on learning Node.JS and MongoDB, so maybe I've missed something.
Thank you in advance!
As Neil Lunn suggested, I checked the user field type and it was indeed of type String instead of ObjectId so there was a mismatch of types between the data stored in collection and the field type from the query.
I used this code to convert the user field type from String to ObjectId in my collection:
db.getCollection('posts').find().forEach(function (post) {
db.getCollection('posts').remove({ _id : post._id});
tempUserId = new ObjectId(post.user);
post.user = tempUserId;
db.getCollection('posts').save(post);
}
);
Now everything works as expected.

Add document to an embedded document array

I'm trying to add an embedded document to an existing document field. I found one fitting answer with the search but I'm running into errors. I'm using node.js, Express and Mongoose.
My database schemas:
var entry = new Schema({
name : { type : String, required : true},
description : { type : String, default: ""},
});
var compo = new Schema({
name : String,
description : String,
entries : [entry]
});
And I'm trying to update the entries array with the following code
var entry = new entryModel();
entry.name = "new name";
entry.description= "new description";
compoModel.findOne(query, function (err, item) {
if (item) {
item.entries.push(entry);
item.save(function (err) {
if (!err) {
log.debug('Entry added successfully.');
} else {
log.error("Mongoose couldn't save entry: " + err);
}
});
}
});
It yields an error: TypeError: Object.keys called on non-object
What have I missed?
So I managed to get it working via the Model.update method by simply adding a new object to the compo.entries list and calling compoModel.update.
My similar issue (same error) was solved by clearing the sub-document array. It was populated prior to the definition of the sub-document scheme. At least this is what i think happened.
E.g.:
var token = new Schema( { value: String, expires: Date } )
var user = new Schema( { username: String, tokens: [token] } )
.. and, prior to defining the 'token' scheme i had entries such as:
{ username: 'foo', tokens: ['123456'] }
.. so, clearing tokens did it for me.
user.tokens = []
user.save()

Resources