Meteor Mongo adding data to an existing collection - mongodb

I currently have the the collection "Plans" and it is made upon the creation of a form submit. It inserts the following:
Plans.insert({
location,
address,
date,
time,
notes,
createdAt: new Date(), // current time
owner: Meteor.userId(),
username: Meteor.user().username,
attendees: [
{
attender: [{
user: String,
attending: Boolean,
}],
},
],
});
Then, upon a click of a checkbox, I want a new attender object to be added to the attendees array. So far I have tried to do:
'click .notattending'() {
Plans.insert(
{_id: this._id,
attendees: [{
attender: [
{
user: Meteor.user().username,
attending: false,
}
],
}
]
},
);
},
However it isn't adding to the Mongo collection. Is this the correct way to go about doing it?

You can try this to based on your schema.
Plans.update({ _id: this._id }, {
$push: {
attendees: { user: "", attending: true },
},
});

Related

Getting directly an array from a mongoose model

I'm trying to query directly to an array inside of an mongoose document, but for the moment i have couldn't.
The document example:
{
_id:62141a799b646c7926fcfa9c
firstname:"firstname"
lastname:"lastname"
username:"username"
phone:"0000-0000000"
email:"Example#mail.com"
email_verified_at:null
password:"$2a$10$LUATvtyPmlojHVdCkxP/QO9UUzQgOoGCW6xyx8YPUZkt5l7j6kHxK"
remember_token:null
deleted_at:null
created_at:2022-02-21T23:04:25.097+00:00
updated_at:2022-02-21T23:04:25.097+00:00
notes: [
"621954b8f073154099b92fca"
"62142c426ca950e33baa1302"
]
I have a query that works but i think that isn't the most optimal approach, altough i could be wrong.
I want to get something like this:
[
"621954b8f073154099b92fca"
"62142c426ca950e33baa1302"
]
or populated:
[
{
_id: new ObjectId("621954b8f073154099b92fca"),
user: new ObjectId("62141a799b646c7926fcfa9c"),
type: new ObjectId("62076ce385b4eea8c5aeb8ba"),
title: 'qwasdasd',
content: '',
created_at: 2022-02-25T22:14:16.515Z,
updated_at: 2022-02-25T22:14:16.515Z
},
{
_id: new ObjectId("62142c426ca950e33baa1302"),
user: new ObjectId("62141a799b646c7926fcfa9c"),
type: new ObjectId("62076ce385b4eea8c5aeb8ba"),
title: 'qwasdasd',
content: '',
created_at: 2022-02-25T22:14:16.515Z,
updated_at: 2022-02-25T22:14:16.515Z
}
]
And even if i need to find an specific field, search it, but with the query:
const notes = await collection.findOne({ _id: '62141a799b646c7926fcfa9c', notes: { _id: '621954b8f073154099b92fca' } }, { 'notes.$._id': true });
i have this rersult:
{
_id: new ObjectId("62141a799b646c7926fcfa9c"),
notes: [
"621954b8f073154099b92fca"
]
}
or populated:
{
_id: new ObjectId("62141a799b646c7926fcfa9c"),
notes: [
{
_id: new ObjectId("621954b8f073154099b92fca"),
user: new ObjectId("62141a799b646c7926fcfa9c"),
type: new ObjectId("62076ce385b4eea8c5aeb8ba"),
title: 'qwasdasd',
content: '',
created_at: 2022-02-25T22:14:16.515Z,
updated_at: 2022-02-25T22:14:16.515Z
}
]
}
And i know that i can reach it filtering the ObjectId from user with '-_id notes.$._id' instead of { 'notes.$._id': true } and then destructuring the main object with a const { notes } resulting in this code:
const { notes } = await collection.findOne({ _id: '62141a799b646c7926fcfa9c', notes: { _id: '621954b8f073154099b92fca' } }, '-_id notes.$._id' );
But, it's the best approach to do this? Could i do it in different way being able to take advantage of findOne options like, skip, etc...?
PD: If there's some error it's because it's not the original code, i have modified it because in original code there're many abstractions.
Thanks in advance.

MongoDB - remove many from arrays of all existing elements

I have some simple user data. Here is example for one user:
const userSchema = new Schema({
userName: {
type: String,
},
projectsInput: [
{
type: Schema.Types.ObjectId,
ref: "Project",
},
],
projectsHold: [
{
type: Schema.Types.ObjectId,
ref: "Project",
},
],
});
I want by having ProjectId to be able to remove all records from all users that contains it.
if I get the first one
60f02d21159c4b4110f21a32
how I can perform updateMany function for my UserModel?
return UserModel.updateMany(
{
projectsInput: {
$elemMatch: args.projectId,
},
},
{
projectsInput: {
$slice: [projectsInput.$, 1],
},
}
);
})
Here is my code that is not working.
args.projectId = 60f02d21159c4b4110f21a32 (my id for the project I want to delete)
and UserModel is my mongodb Schema for user.
you can use $pull
{
$pull: {
projectsInputs: "123"
}
}

Find if an array present in the mongo Database

This is my Conversation Schema
const ConversationSchema = new Schema({
recipients: [{ type: Schema.Types.ObjectId, ref : 'User' }],
lastMessage: {
type: String,
default: ''
},
date: {
type: Date,
default: Date.now()
},
})
I want to know if there exist an array [ patientId, doctorId ]
Here is my main approach to find
I am not able to get the response and I already have one document with that same array
const conversationBetween = await Conversation.findOne(
{
recipients: {
$all: [
{ $elemMatch: { $eq: patientId }},
{ $elemMatch: { $eq: doctorId }}
],
}
}
)
if (conversationBetween) {
return res.status(401).json({
status: "failed",
message: "You already have a conversation with this doctor"
});
}
following Code to add a Conversation in the Conversation Collection, this works fine
const newConversation = new Conversation({
recipients: [ patientId,doctorId ],
lastMessage: `I want to get consultation`,
date: Date.now(),
})
await newConversation.save()
res.status(200).json({
status: "success",
message: "Conversation added successfully",
conversation: newConversation
});
The main purpose is to make sure that if there present an entry with [ patientId, doctorId ] in Conversation it should not make a new entry..
But at this time its not able to find and is making that same entry.
You can do this
await Conversation.findOne(
{
recipients: [patientId, doctorId]
}
)
Working in Playground

Mongodb pull from array attached to simple schema

I have the following collection attached to aldeed:simple schema
Posts = new Mongo.Collection("posts");
Posts.attachSchema(new SimpleSchema({
samplePost:{
type:String,
max:500
},
createdAt:{
type: Date,
autoValue: function(){
return new Date()
}
},
"comments.$.reply":{
type:String
},
"comments.$.commentId":{
type: String,
autoValue: function(){
var tempCommentId = new Meteor.Colletion.ObjectID();
return tempCommentId.str;
}
},
"comments.$.commentCreatedAt": {
type: Date,
optional: true,
autoValue: function(){
return new Date()
}
},
});
The actual document looks like the following:
{
"_id": "aaa",
"samplePost": "Hello world!",
"comments": [
{
"reply": "Goodbye",
"commentId": "bbb",
"createdAt": "2016-06-19T19:06:17.931Z"
},
{
"reply": "Good morning",
"commentId": "ccc"
"createdAt": "2016-06-19T19:05:17.931Z"
},
]
}
Now im trying to remove only the 2nd comment with commentId:"ccc" from the document with $pull
"click #delete-comment": function(event, template){
var tempCommentId = $(event.target).parent().find('#commentIdPass').text(); //commentId is collected from HTML view
Posts.update(
{_id: template.data._id}, //_id is collected from the url param
{$pull:{
comments: {
commentId: tempCommentId
}}
});
},
and this is not working. I have narrowed down the problem to
"comments.$.commentCreatedAt": {
type: Date,
optional: true,
autoValue: function(){
return new Date()
}
},
schema. If i remove this schema, i can delete the comment.
So, why is this causing a problem of pulling the whole comment item from the array. Any ideas? Any workarounds?
Try This Query:
db.getCollection('Mytest').update({"_id":"aaa"},{"$pull":{"comments":{"commentId":"ccc"}}});
Found the problem. As I have suspected attached schema was the culprit. I needed to set a conditional for inserting and updating a schema with autovalue method. The schema should look as following:
"comments.$.commentCreatedAt": {
type: Date,
autoValue: function () {
if (this.isInsert) {
return new Date;
}
}
},

auto increment ids in mongoose

How do I have autoincrement ids in mongoose? I want my ids to start like 1, 2, 3, 4, not the weird id numbers mongodb creates for you?
Here's my schema:
var PortfolioSchema = mongoose.Schema({
url: String,
createTime: { type: Date, default: Date.now },
updateTime: { type: Date, default: Date.now },
user: {type: Schema.Types.ObjectId, ref: 'User'}
});
Use mongoose-auto-increment:
https://github.com/codetunnel/mongoose-auto-increment
var mongoose = require('mongoose');
var autoIncrement = require('mongoose-auto-increment');
var connection = ....;
autoIncrement.initialize(connection);
var PortfolioSchema = new mongoose.Schema({
url: String,
createTime: { type: Date, default: Date.now },
updateTime: { type: Date, default: Date.now },
user: {type: Schema.Types.ObjectId, ref: 'User'}
});
//Auto-increment
PortfolioSchema.plugin(autoIncrement.plugin, { model: 'Portfolio' });
module.exports = mongoose.model('Portfolio', PortfolioSchema);
Or if you prefer to use an additional field instead of overriding _id, just add the field and list it in the auto-increment initialization:
var PortfolioSchema = new mongoose.Schema({
portfolioId: {type: Number, required: true},
url: String,
createTime: { type: Date, default: Date.now },
updateTime: { type: Date, default: Date.now },
user: {type: Schema.Types.ObjectId, ref: 'User'}
});
//Auto-increment
PortfolioSchema.plugin(autoIncrement.plugin, { model: 'Portfolio', field: 'portfolioId' });
If you want to have a incrementing numeric value in _id then the basic process is you are going to need something to return that value from a store somewhere. One way to do this is use MongoDB itself to store data that holds the counters for the _id values for each collection, which is described within the manual itself under Create and Auto-Incrementing Sequence Field.
Then as you create each new item, you use the implemented function to get that "counter" value, and use it as the _id in your document.
When overriding the default behavior here, mongoose requires that you both specify the _id and it's type explicitly with something like _id: Number and also that you tell it to no longer automatically try to supply an ObjectId type with { "_id": false } as an option on the schema.
Here's a working example in practice:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var counterSchema = new Schema({
"_id": String,
"counter": { "type": Number, "default": 1 }
},{ "_id": false });
counterSchema.statics.getNewId = function(key,callback) {
return this.findByIdAndUpdate(key,
{ "$inc": { "counter": 1 } },
{ "upsert": true, "new": true },
callback
);
};
var sampleSchema = new Schema({
"_id": Number,
"name": String
},{ "_id": false });
var Counter = mongoose.model( 'Counter', counterSchema ),
ModelA = mongoose.model( 'ModelA', sampleSchema ),
ModelB = mongoose.model( 'ModelB', sampleSchema );
async.series(
[
function(callback) {
async.each([Counter,ModelA,ModelB],function(model,callback) {
model.remove({},callback);
},callback);
},
function(callback) {
async.eachSeries(
[
{ "model": "ModelA", "name": "bill" },
{ "model": "ModelB", "name": "apple" },
{ "model": "ModelA", "name": "ted" },
{ "model": "ModelB", "name": "oranage" }
],
function(item,callback) {
async.waterfall(
[
function(callback) {
Counter.getNewId(item.model,callback);
},
function(counter,callback) {
mongoose.model(item.model).findByIdAndUpdate(
counter.counter,
{ "$set": { "name": item.name } },
{ "upsert": true, "new": true },
function(err,doc) {
console.log(doc);
callback(err);
}
);
}
],
callback
);
},
callback
);
},
function(callback) {
Counter.find().exec(function(err,result) {
console.log(result);
callback(err);
});
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
For convience this implements a static method on the model as .getNewId() which just descriptively wraps the main function used in .findByIdAndUpdate(). This is a form of .findAndModify() as mentioned in the manual page section.
The purpose of this is that it is going to look up a specific "key" ( actually again the _id ) in the Counter model collection and perform an operation to both "increment" the counter value for that key and return the modified document. This is also aided with the "upsert" option, since if no document yet exists for the requested "key", then it will be created, otherwise the value will be incremented via $inc, and it always is so the default will be 1.
The example here shows that two counters are being maintained independently:
{ _id: 1, name: 'bill', __v: 0 }
{ _id: 1, name: 'apple', __v: 0 }
{ _id: 2, name: 'ted', __v: 0 }
{ _id: 2, name: 'oranage', __v: 0 }
[ { _id: 'ModelA', __v: 0, counter: 2 },
{ _id: 'ModelB', __v: 0, counter: 2 } ]
First listing out each document as it is created and then displaying the end state of the "counters" collection which holds the last used values for each key that was requested.
Also note those "weird numbers" serves a specific purpose of always being guranteed to be unique and also always increasing in order. And note that they do so without requiring another trip to the database in order to safely store and use an incremented number. So that should be well worth considering.