ObjectIDs in other collections without getting duplicate key error - javascript

I am getting the following error when trying to create a document in a collection.
MongoServerError: E11000 duplicate key error collection: stock-trading-system-db.trades index: user_id_1 dup key: { user_id: ObjectId('6266de71b90b594dab9037f3') }
Here is my schema:
const tradeSchema = new mongoose.Schema({
user_id: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
stock_id: {
type: Schema.Types.ObjectId,
ref: 'Stock',
required: true
},
stock_amount: {
type: Number,
required: true
},
stock_value: {
type: Number,
required: true
},
time_of_trade: {
type: Date,
required: true,
default: new Date()
},
trade_status: {
type: String,
enum: ['Approved', 'Declined', 'Pending'],
required: true,
default: 'Pending'
}
}, { collection: 'trades' })
I don't want user_id and stock_id to be unique, i just want it to check that those ObjectIDs exist in their respective collections before making the trade document. How do i achieve this?

It looks like a collection saves the schema that is defined in mongoose, and even if you change the schema, the unique values will stay the same inside the collection.
So even though i had removed
unique: true;
from my mongoose schema, it hadn't removed this from the collection in my DB.
Therefore the solution to this is to delete the collection and recreate it.

Related

How do I populate a array of dictionaries of objects in mongoose? [duplicate]

I have a Mongoose schema with an array lists of objects that consist of a reference to another collection and a nested array of numbers:
var Schema, exports, mongoose, schema;
mongoose = require("mongoose");
Schema = mongoose.Schema;
schema = new Schema({
name: {
type: String,
required: true,
unique: true,
trim: true
},
lists: [{
list: {
type: Schema.ObjectId,
require: true,
ref: "List"
},
allocations: [{
type: Number,
required: true
}]
}],
createdAt: {
type: Date,
"default": Date.now
},
updatedAt: {
type: Date
}
});
exports = module.exports = mongoose.model("Portfolio", schema);
However, I cannot get populate to work as expected without getting a TypeError: Cannot read property 'ref' of undefined. I've tried populate('list') and populate('lists list') but I'm either not calling things correctly or my Schema isn't formed correctly. I don't have this problem if I simply reference the lists by themselves:
lists: [{
type: Schema.ObjectId,
require: true,
ref: "List"
}]
but I want to have the allocations array alongside each list. What do I need to do to get the behavior I want?
I found the answer: populate('lists.list') works. Thanks to this question: Mongoose populate within an object?
Actual answer:
Use this,
populate('lists.list')
Extra:
Here are lists are an array of objects (list).
In JS you can access this like that,
console.log(lists.list);
and MongoDB syntax is 99% similar to JS syntax.
so....................
lists: [{
list: {
type: Schema.ObjectId,
require: true,
ref: "List"
},
allocations: [{
type: Number,
required: true
}]
}],
=> Because it's an array of objects, you can do this -: Portfolio.populate('lists.list');
2.
lists: [{
type: Schema.ObjectId,
require: true,
ref: "List"
}]
=> Because it's an array, you just have to do this -: Portfolio.populate('lists');
if you have nested schema
YourSchema.find()
.populate({
path: 'map_data',
populate: {
path: 'location'
}
})
it's work for me
// Cart schema
var CartSchema = new mongooseSchema({
productDetails: [{
productId: {
type: mongoose.Schema.ObjectId,
required: true,
ref: 'Product'
},
productCount: Number,
}],
UserId: {
type: String,
default: '',
required: true,
trim: true,
},
shopId: {
type: String,
default: '',
required: true,
trim: true,
},
});
// add this .populate('productDetails.productId').
db.Cart.find({
UserId: userId,
shopId: shopId
}).populate('productDetails.productId')
.skip(pagination.skip)
.limit(pagination.limit)
.exec(function(error,
CartList) {
if (error) {
callback(error, null)
} else {
callback(null, CartList)
}
});
Populate didn't work in my case when nesting to array my Schema was
const chatSchema = mongoose.Schema({
chats: [{
type: Schema.Types.ObjectId,
ref: "ChatMsg"
}],
})
How I solved it
Chat.findOne({
customer: req.body.customer,
agency: req.body.agency
}, (err, chat) => {
if (err) {
res.status(422).send("Our fault");
}
chat.populate("chats").execPopulate(() => {
res.send(chat);
});
});

Node mongodb stores data as string instead of an object

I have two same functions, first saves some stuff and also saves ref to productId and second saves another stuff and saves ref to productId too. The problem is first writes ref to poductId as object and everything is ok but second function saves ref as string and in mongodb i see ObjectId but when im trying to display data on screen i cant access into object i have only string with ID of refer. Any ideas?
first model which is ok
const mongoose = require('mongoose')
const dishPositionsSchema = mongoose.Schema({
productId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Products'
},
dishId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Dishes'
},
weight: {
type: Number,
required: true
}
})
module.exports = mongoose.model('DishPositions', dishPositionsSchema)
and second which stores only strings instead of objects
const mongoose = require('mongoose')
const diaryPositionsSchema = mongoose.Schema({
productId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Products'
},
dishId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Dishes'
},
weight: {
type: Number,
required: true,
required: true
},
timeOfEatingId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'TimeOfEating'
},
date: {
type: String,
required: true
}
})
module.exports = mongoose.model('DiaryPositions', diaryPositionsSchema)
I know where i did mistake... i didnt write populate('productId')... everything is fine now thanks!

searching for an array in a schema by id

const FormFieldsSchema = new Schema({
formName: {
type: String,
required: true
},
fields: [
{
fieldLabel: {
type: String,
required: true
},
inputData: [{
type: mongoose.Schema.ObjectId,
ref: "UserData"
}]
}
]
});
Hi guys, I have a schema in which fields is an array, now for every array item I have an _id property, I wish to find that array and update it, but I can't manage to do it,
I tried findByIdAndUpdate, but it didnt work, also tried parent.inputData.id(_id); no luck yet, any ideas?
Convert the content of your array into a separate model, then you can query the model directly.
running findByIdAndUpdate on FormFieldsSchema fill search for the _id of FormFields not the content of fields array.
const FieldSchema = new Schema({
fieldLabel: {
type: String,
required: true
},
inputData: [{
type: mongoose.Schema.ObjectId,
ref: "UserData"
}]
})
and change field into fields: [FieldSchema]
also, don't forget to export FieldSchema as a model.

Mongoose schema update is not pick it up by Mongodb database

I've my db already created where I have the following schema:
const ProjectSchema = new mongoose.Schema({
name: { type: String },
description: { type: String },
client: {
type: mongoose.Schema.Types.ObjectId,
ref: 'client'
},
group: {
type: mongoose.Schema.Types.ObjectId,
ref: 'project_group'
}
});
I need to change the schema to
const ProjectSchema = new mongoose.Schema({
name: { type: String, unique: true, required: true },
description: { type: String },
client: {
type: mongoose.Schema.Types.ObjectId,
ref: 'client'
},
group: {
type: mongoose.Schema.Types.ObjectId,
ref: 'project_group'
}
});
because we need to force name to be unique and not null. After change this definition, I see that the db still saving documents with the same name value. My question is, how can I apply any change I've done in my schema? and, how can I do that automatically without doing this manually?
Regards
You most likely need to index that field so it can be quickly searched. Then also restart your server, if you haven't already. It's easy to do if you have MongoDB Compass (the official MongoDB GUI), or you can read this doc.
https://docs.mongodb.com/manual/core/index-single/#create-an-index-on-an-embedded-field

Duplicate key error collection with unique field

I am getting a MongoDB error when trying to insert a document without nickname second time. The document already have unique field and non required.
Here is my Mongoose model:
var schema = new Schema ({
username: {
type: String,
required: false
},
nickname: {
type: String,
required: false,
unique: true,
trim: true
},
status: {
type: String,
required: false,
trim: true,
minlength: 1,
maxlength: 100
},
avatar: String,
online: {
type: Boolean,
default: false
},
created: {
type: Date,
default: Date.now
},
device: {
type: ObjectId,
ref: 'Device',
required: false
},
createdRooms:[{
type: Schema.Types.ObjectId,
ref: 'Room'
}],
facebook: {
facebookToken: {
type: String,
required: false,
trim: true,
unique: false
},
facebookId: {
type: String,
required: false,
trim: true,
unique: false
}
}
},
{
toObject: {
virtuals: true
},
toJSON: {
virtuals: true
}
});
For the first time, the document without a nickname is added to the database, but when I want to save another document without a nickname, I get an error:
MongoError: E11000 duplicate key error collection: grooptag.users index: nickname_1 dup key: { : null }
So I looked up "MongoDB not required but unique" and I found this: mongoDB/mongoose: unique if not null
It seems you need to use sparse: true instead of required: false to get what you want.
Edit: Reading up the MongoDB documentation on sparse indexes, however, I was redirected to partial indexes which seem to be the way to go from MongoDB 3.2 onward: https://docs.mongodb.com/manual/core/index-partial/#index-type-partial
The problem is that while the documentation clearly states:
Partial indexes represent a superset of the functionality offered by sparse indexes and should be preferred over sparse indexes.
It does not seem to be true for sparse and unique indexes, since they also state on the same page:
A partial index with a unique constraint does not prevent the insertion of documents that do not meet the unique constraint if the documents do not meet the filter criteria.
Way to contradict themselves... :/

Categories

Resources