ExpressJS - duplicate key error collection - javascript

I have problem with this error when I am creating a new event with category which exists in my database, for example I created an event with category "javascript" and save it to db, and then i tried to create a new event with categories "javascript, html, css" and then i got this error duplicate key error collection
So my schema for event is this:
const EventSchema = new Schema({
title: {
type: String,
required: true,
min: 3,
max: 100
},
featuredImage: {
type: Object,
},
from: {
type: Date,
required: true
},
to: {
type: Date,
required: true
},
location: {
name: {
type: String
},
address: {
type: Object
}
},
description: {
type: String
},
categories: {
type: Array,
trim: true
},
featured: {
type: Boolean
},
created_by: {
type: Schema.Types.ObjectId,
ref: 'User'
},
slug: {
type: String,
default: null
},
registration: {
type: Boolean
},
tickets: [],
allday: {
type: Boolean
},
speakers: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
attendees: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
comments: [CommentSchema]
}, {
timestamps: true,
usePushEach: true
});
So basically sending array of strings and i got this error.

You probably have some index defined on categories with the unique flag.
You can list the existing indexes with db.events.getIndexes().
You could drop and recreate the culprit (be careful):
> db.events.dropIndex({categories:1})
> db.events.ensureIndex({categories:1},{sparse:true})

Related

MongoDB (mongoose) filter with value in array with reference

I am trying to filter an array in a document in mongoose.
The problem i am having is trying to filter with a value in the array that is in the reference.
To clarify, i have a document containg all the information about a course. In that course i have a array of objects that contains information about students. An object containts a status and also a refrence to the actual user object. I would like filter the students array with a value found in the refrence.
The way i have tested this is as following:
courseModel.findOne({ _id: courseId, 'students.user.startDate': { $lte: startDate } });
My models look like this:
CourseModel:
{
name: {
type: String,
required: true,
maxlength: 50,
minlength: 2,
trim: true
},
description: {
type: String,
required: false,
maxlength: 500,
trim: true
},
type: {
type: String,
required: true,
enum: ['physical', 'online', 'quiz']
},
color: {
type: String,
required: true,
match: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
},
events: [
{
type: Schema.Types.ObjectId,
ref: 'event'
}
],
questions: [
{
type: Schema.Types.ObjectId,
ref: 'question'
}
],
educators: [
{
type: Schema.Types.ObjectId,
ref: 'user'
}
],
students: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
status: {
type: String,
enum: ['notBooked', 'booked', 'attended', 'completed']
},
lastSlackMessage: {
ts: {
type: String
},
channel: {
type: String
}
},
events: [
{
type: Schema.Types.ObjectId,
ref: 'event'
}
]
}
],
teams: [
{
type: Schema.Types.ObjectId,
ref: 'team'
}
],
createdBy: {
type: Schema.Types.ObjectId,
ref: 'user'
},
updatedBy: {
type: Schema.Types.ObjectId,
ref: 'user'
}
}
UserModel:
{
name: {
type: String,
required: true,
maxlength: 100,
trim: true
},
email: {
type: String,
required: true,
minlength: 5,
match: /^(([^<>()[\]\\.,;:\s#"]+(\.[^<>()[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
},
employeeId: {
type: String,
required: true
},
slackId: {
type: String,
default: ''
},
teams: [
{
type: Schema.Types.ObjectId,
ref: 'team'
}
],
questions: [
{
question: {
type: Schema.Types.ObjectId,
ref: 'question'
},
status: {
type: String,
enum: ['answered', 'pending', 'notSent']
},
tries: {
type: Number,
default: 0
}
}
],
startDate: {
type: Date,
required: true
}
}
I appreciate any help i can get, thank you!

How to UPDATE on Child, the reference of Parent upon Parent deletion?

I'm making this question since I'm having a hard time asking the right question when I research. I hope to be clear:
I've got 2 Schemas:
Parent [TEAM]:
const EquipaSchema = new mongoose.Schema({
trab1: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Trab'
},
trab2: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Trab'
},
trab3: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Trab'
},
teamName: {
type: String,
required: true
},
marcsEquipa: [{
type: Schema.Types.ObjectId,
ref: 'Marcacao'
}]
},
{collection: 'Equipas'})
And Child [Project]:
const MarcacaoSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true },
date: { type: Date, required: true},
hour: { type: String, required: true},
type: { type: String, required: true},
address: {type: String, required: true},
state: {type: String, default: 'Pendente'},
// equipa: { type: Schema.Types.ObjectId, ref: 'Equipa' },
equipa: {
type: String,
default: 'Não'
},
cliente: {
type: Schema.Types.ObjectId,
ref: 'User'
},
aval_admin: {
type: String,
default: "Sem Avaliação pelo Manager"
},
descricao: {
type: String,
default: "Sem Descrição"
},
aval_client: {
type: String,
default: "Sem Avaliação do Cliente"
},
avaliado: {
type: Boolean,
default: false
},
team: {
type: Schema.Types.ObjectId,
ref: 'Equipas'
}
},
{collection: 'Marcacao'}
My goal is: When a team is deleted, all of the projects in the team array ['marcsEquipa[]'] get updated to {team: null}, so that I can assign a NEW team to the SAME project.
I've tried using middlewares, but some of its usages are now deprecated and had no success. Whats the correct way to solving this problem?
Thank you in advance
await Marcacao.updateMany({team: req.params._id}, {team: null});
This was the solution. Where req.params._id is the team ID.

mongo query $near always 0 results

My search Position is the same as the position in the database. The result is an empty array. I expected to get the one element from database, because the distance between both locations is 0.
Mongo Doku $near
Query to find all nearest
Request.find({
address: {
location: {
$near: {
$geometry: {
type: 'Point' ,
coordinates: [8.4821159,49.4705199],
},
$maxDistance: 10000,
$minDistance: 0,
},
},
},
})
Mongoose Model
Edit (add): this.request.index({'address.location': '2dsphere'});
import mongoose from 'mongoose';
const ObjectId = mongoose.Schema.Types.ObjectId;
import {RequestMiddleware} from './RequestMiddleware';
class Request extends mongoose.Schema {
public request: mongoose.Schema;
constructor() {
const RequestSchema = {
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
category: {
type: ObjectId,
ref: 'Category',
required: true,
},
created_by: {
type: ObjectId,
ref: 'User',
required: true,
},
address: {
location: {
type: {
type: String,
enum: ['Point'],
default: 'Point',
required: true,
},
coordinates: {
type: [Number],
default: [0, 0],
required: true,
},
},
plz: {
type: String,
required: false,
},
city: {
type: String,
required: false,
},
street: {
type: String,
required: false,
},
street_nr: {
type: String,
required: false,
},
},
time_end: {
type: Date,
required: false,
},
confirmed_helper: {
type: ObjectId,
ref: 'User',
},
helper: [{
helperId: {
type: ObjectId,
ref: 'User',
},
offer_text: {
type: String,
},
}],
};
const request = super(RequestSchema, {
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at',
},
});
this.request = request;
this.request.index({'address.location': '2dsphere'});
this.request.plugin(RequestMiddleware);
return this.request;
}
}
export default mongoose.model('Request', new Request());
Database:
You need two things:
2dspere index (probably you already have it):
db.col.createIndex( { "address.location" : "2dsphere" } )
and to modify your query so that it uses the dot notation instead of nested object:
let result = await Request.find({
'address.location': {
$near: {
$geometry: {
type: 'Point',
coordinates: [8.4821159, 49.4705199]
},
$maxDistance: 10000,
$minDistance: 0
}
}
});

findByIdAndUpdate keeps being caught in .catch

So when I am executing my findByIdAndUpdate it doesn't execute my promise as expected and goes into my catch. I sent responses to postman and using res.json(req.user.id) and res.json(profileFields) . This is the response I get when I use
profileFields
{
"user": "5b3134a0e2543b06d130a5d7",
"handle": "wadeaston1",
"status": "Developer",
"skills": [
"HTML",
" CSS",
" Javascipt"
],
"social": {}
}
i'm at a loss here because all my fields are passing in the values as expected into user and $set. I don't understand why its going to my catch
Profile.findByIdAndUpdate(
{ user: req.user.id },
{ $set: profileFields },
{ new: true }
)
.then(profile => res.json(profile))
.catch(err => {
res.json("Timeout");
console.log("HI");
});
Here is my Profile Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
//Create Scheme
const ProfileSchema = new Schema({
user: {
//this will associate user by their ID
type: Schema.Types.ObjectId,
ref: "users"
},
handle: {
type: String,
required: true,
max: 40
},
company: {
type: String
},
website: {
type: String
},
location: {
type: String
},
status: {
type: String,
required: true
},
skills: {
//Array of strings
type: [String],
required: true
},
bio: {
type: String
},
githubusername: {
type: String
},
experience: [
{
title: {
type: String,
required: true
},
company: {
type: String,
required: true
},
location: {
type: String
},
from: {
type: Date,
required: true
},
to: {
type: Date,
required: true
},
current: {
type: Boolean,
default: false
},
description: {
type: String
}
}
],
education: [
{
school: {
type: String,
required: true
},
degree: {
type: String,
required: true
},
fieldofstudy: {
type: String,
required: true
},
from: {
type: Date,
required: true
},
to: {
type: Date,
required: true
},
current: {
type: Boolean,
default: false
},
description: {
type: String
}
}
],
social: {
youtube: {
type: String
},
twitter: {
type: String
},
facebook: {
type: String
},
linkedin: {
type: String
},
instagram: {
type: String
}
},
date: {
type: Date,
default: Date.now
}
});
module.exports = Profile = mongoose.model("profile", ProfileSchema);
findByIdAndUpdate is for finding the document to update by its _id value, but you need to find the document by its user field, so you should be using findOneAndUpdate instead:
Profile.findOneAndUpdate(
{ user: req.user.id },
{ $set: profileFields },
{ new: true }
)
.then(...
No need to manually cast req.user.id to an ObjectId as Mongoose will do that for you based on the way user is defined in your schema.
Based on the error you gave, it looks like you need to turn req.user.id from a string to an ObjectId:
Profile.findByIdAndUpdate(
{ user: new mongoose.Types.ObjectId(req.user.id) },
{ $set: profileFields },
{ new: true }
).then( /* rest of code */
This assumes you did a const mongoose = require('mongoose') or similar.

Save JSON object to MongoDB inside String field

I'm working with Mongodb(mongoose) and node.js (express.js).
The model of DB is:
var messageSchema = new Schema({
_channel: { type: Schema.ObjectId, ref: 'Channel', required: true },
_user : { type: Schema.ObjectId, ref: 'User', required: true },
datetime: { type: Date, required: true },
messageType: { type: String, required: true },
publish: { type: Boolean, default: false },
content: {
title: String,
text: String,
}
});
I want save JSON object inside text field (string).
The JSON object is this:
{ event: 'push',
repository: { id: 53012902, name: 'RestAPI' },
ref: 'refs/heads/master',
commits:
[ { id: 'a10202e5b5157ae5ccd2d77d7d578046693ae404',
url: 'https://github.com/1izpena/RestAPI/commit/a10202e5b5157ae5ccd2d77d7d578046693ae404',
author: '1izpena' } ],
sender: { login: '1izpena', html_url: 'https://github.com/1izpena' } }
I convert this in String, but the result is:
{"event":"push","repository":{"id":53012902,"name":"RestAPI"},"ref":"refs/heads/master","commits":[{"id":"a10202e5b5157ae5ccd2d77d7d578046693ae404","url":"https://github.com/1izpena/RestAPI/commit/a10202e5b5157ae5ccd2d77d7d578046693ae404","author":"1izpena"}],"sender":{"login":"1izpena","html_url":"https://github.com/1izpena"}}
And this result is not a String, I need to keep the same format to parse it later as json object.
Any idea?
Many thanks

Categories