how to make a mongoose query to search for matching arrays - node.js

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
{
}

Related

Weird behavior with mongoose Schema $inc operator

I'm working a todo app, it has projects and each project has todolistsand todoListsCount .
When user creates a new todoList I want to increment the project's todoListsCount, the problem I found is that somehow after creating the first todoList the project's todoListsCount successfully increment but the new value is 2 I suppose to what I was expecting which is 2 :
let project= null
await Project.findOneAndUpdate(
{_id:projectId},
{ $inc:{ todoListsCount:1 }},
{ new: true},
(err, doc) => {
if (err)console.log("Something wrong when updating data!");
project =doc
}
);
const todoList = new TodoList({
title,
owner,
projectId,
orderInProject : project.todoListsCount,
created_at : new Date(),
progress : 0,
done_at : new Date(),
todos : [],
done : false,
})
await todoList.save()
as you can see in the Project schema default value of todoListsCount is 0
import mongoose from 'mongoose'
const Schema = mongoose.Schema;
const ProjectSchema = new Schema(
{
/..rest of fields
todosCount : {
type : Number ,
required :false ,
default: 0
},
todoListsCount : {
type : Number ,
required :false ,
default: 0
},
}
)
export const Project = mongoose.model('Project', ProjectSchema);
I guess you are using both await and callback for same function, can be the culprit. Try:
let project = await Project.findOneAndUpdate(
{_id:projectId},
{ $inc:{ todoListsCount:1 }},
{ new: true}).exec();

How do I prevent a field update in moongoose

I have a schema that looks like this :
"use strict"
const mongoose = require('mongoose');
const timestamp = require('mongoose-timestamp');
const CustomerSchema = new mongoose.Schema({
name : {
type : String,
required : true,
trim : true
},
email : {
type : String,
required : true,
trim : true
},
balance : {
type : Number ,
default : 0
}
})
//use timestamps to add created at and updated at
CustomerSchema.plugin(timestamp);
const Customer = mongoose.model('Customer',CustomerSchema);
module.exports = Customer;
When I want to run an update , I run this code
const Customer = require('../models/Customer');
const customer = await Customer.findOneAndUpdate({_id : req.params.id}, req.body);
so req.body carries the data that will be updated
The problem is that I do not want people to update the email field .
So my question is :
How do I lock the email field from being updated . Is there a way to lock it in the schema , so that it can only be added initially but not updated later ?
Thanks .
There is a property you can define at the schema level called immutable.
Reference to documentation: https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-immutable
So your schema would look like this:
const CustomerSchema = new mongoose.Schema({
name : {
type : String,
required : true,
trim : true
},
email : {
type : String,
required : true,
trim : true,
immutable: true // ADD THIS PROPERTY HERE
},
balance : {
type : Number ,
default : 0
}
}
There is no functionality to prevent from update
You can do by removing email object from body
delete req.body.email;
const customer = await Customer.findOneAndUpdate({_id : req.params.id}, req.body);

Mongoose Schema Type String not working

I'm updating on my database, but I'm having trouble understanding what is happening with my schema below:
{
ref : String,
event : {
name : String,
data : mongoose.Schema.Types.Mixed,
type : mongoose.Schema.Types.Mixed, // Declaring this as String makes parent(event) undefined.
}
}
The input data to event.type are strings, but when I declare it as such, the event field for all existing and new documents become undefined.
i.e. in the Main Function (below) I get Cannot set property 'type' of undefined
// Main function
model
.find({ 'event.type' : { $exists: false }})
.exec(function(err, data) {
if (err) return console.log(err);
for (var i = 0, len = data.length; i<len; i++) {
data[i].event.type = data[i].ref; // <-- Error Occurs here: Cannot set property 'type' of undefined
data[i].save()
}
})
Would love to get some insight. Any help is appreciated!
The property type has a special meaning in Mongoose.
If you want to use it as a property name in your schema you need to tell Mongoose to not treat as special:
var schema = new Schema({
ref : String,
event : {
name : String,
data : mongoose.Schema.Types.Mixed,
type : String,
}
}, { typeKey : '$type' });
More info here;

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

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

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