$push causing error Updating the path 'x' would create a conflict at 'x' - mongodb

Given the example with Mongoose:
Schema:
const fields = {
...other fields
users: [
{ name: String, email: String, department: String, position: String, _id: false }
]
}
const Company = model('Company', fields);
Update action:
const companyId = 'company-id';
const user = { name: 'John', email: 'john#email.com' }
Company.findByIdAndUpdate(companyId, {
$push: {
users: user
}
}, { new: true })
.lean({ defaults: true })
.exec();
This causes an error:
Updating the path 'users' would create a conflict at 'users'.
I would think this would work correctly and I'm not doing anything else except pushing a new object to the array. Any help would be appreciated. Thanks!

Related

Recursive mongoose schema does not result in correct object stores

I have a recursive model schema defined in a schema which uses the add() method in the Schema class to incrementally build the schema. It seems to build the paths correctly as shown when I print out the paths. However, when I use the Model defined to store the object in the database, it is missing the inner BNode. Here is a definition of the schema:
import mongoose from 'mongoose';
const BNodeSchema = new mongoose.Schema({
bValue: { type: [Number] },
id: String,
})
const RValue = {
rId: String,
value: Number
}
const ANodeSchema = new mongoose.Schema({
type: {
id: String,
rValues: {
type: Map,
of: RValue
},
}
})
const QuestSchema = new mongoose.Schema({
type: {
_id: { type: String, },
aNode: ANodeSchema,
bNodes: [BNodeSchema],
url: {
type: String
},
id: {
type: String
}
},
},
{ id: false }
)
ANodeSchema.add({ quest: QuestSchema });
const QuestNodeSchema = new mongoose.Schema({
_id: { type: String, unique: true },
quests: { type: [QuestSchema] },
}, {
id: false
})
export const QuestModel = mongoose.model('QuestModel', QuestNodeSchema);
QuestNodeSchema.eachPath(function(path:any) {
console.log(path);
});
{
_id: 12223,
quests:[
{
id: 'Quest-111-111' ,
aNode: {
id: 'A222222',
rValues: {
rId: 'RR1222',
value: 44422
},
quest:{
url: 'https://deptio-opcom',
id: '22222-QST',
bNodes:[{
bValue: 'B22190',
value: 22085
}]
}
}
}
]
}
I have included a sample of the json I am storing in the database. I use a class, not included for brevity to create the equivalent JSON object in the final format to be stored. My feeling is that there is something not quite right with my schema definition. I would be most grateful if someone could help me figure out what I am missing in my definition. Thanks a lot

How to rollback mongodb using mongoose

I have an array as below.
const array =
[
{ name: 'Tom',
age: '30'
},
{ name: 'Sam',
age: '24'
}
]
And I create this array using mongoose.
Schema.create(array)
'name' and 'age' are required. Therefore in this case, they are created well.
But When I put this array,
const array =
[
{ name: 'Tom',
age: '30'
},
{ name: 'Sam'}
]
Tom is created but Sam is not created as it doesn' t have age value.
When one of those has an error during create, I want to not save nothing at all.
It's becuase 'front client' have to try insert again when receiving error response.
How can I control transaction using mongo and mongoose? Thank you for reading it.
You can create a Schema model for that and add required to it :
var mongoose = require('mongoose')
const Schema = mongoose.Schema
const myUserSchema = new Schema ({
users : [{
name: {
type: String,
required: true
},
age: {
type: String,
required: true
}
}]
})
var myUser = mongoose.model('myUser', myUserSchema)
Then:
const array =
[
{ name: 'Tom',
age: '30'
},
{ name: 'Sam'}
]
const newUser = new myUser({
users: array
})
newUser.save((err, user)=>{
if (err) {
console.log(err)
}
})
It should validate your array at the time when you try to save it and throw an error in case if something is missing.
Example of thrown error:
ValidationError: myUser validation failed: users.1.age: Path `age` is required

How to get All items associated to a user in mongoose

I have a collection of Items that a particular make and perform a transaction. In my schema, I associate the userId to each item. I want to be able to display as a list all the items that the user owns.
Here I have managed to total up all sizes of each item but I cant work out a way how to get a total for each user
{
id: Number,
x: Number,
y: Number,
xSize: String,
ySize: String,
imageSource: String,
user: { type: mongoose.Schema.ObjectId, ref: 'User' }
},
{ timestamps: true }
);
const UserSchema = new Schema(
{
id: Number,
name: String,
website: String,
},
{ timestamps: true }
);
Item.find({}, function (err, items) {
var itemMap = {};
items.forEach(function (item) {
itemMap[item._id] = item;
});
var countedNames = items.reduce(function (allNames, name) {
if (name.xSize in allNames) {
allNames[name.xSize]++;
}
else {
allNames[name.xSize] = 1;
}
return allNames;
}, {});
Essentially i want to get a list basically saying
{name:"Dave", website:"www.google.com, items:[item1, item2]}
where item1 and item2 relate to the item schema
You should rewrite your UserSchema to contain a reference to the item, in this format:
const UserSchema = new Schema(
{
id: Number,
name: String,
website: String,
items:
[{
item: {type: mongoose.Schema.ObjectId, ref: 'Item'}
}]
},
{ timestamps: true }
);
This will simply allow you to perform the following query:
User.find({}).populate('Item')
Which would return the User document, and all items associated under the document.
You could do the following:
let users = User
.find({})
.populate('Item')
.exec(function (err, users) {
if (err) { console.log(err); }
console.log(users)
}
Rewriting the schema will make querying users for their items much easier.

Why do I get array of nulls in my database? [duplicate]

This question already has answers here:
Node.js Mongoose.js string to ObjectId function
(9 answers)
Closed 4 years ago.
I have an array of ids which is launchIds.
I'm trying to push it on a model field trips with
$addToSet: { trips: { $each: launchIds }. This gives me an error: Cast to [ObjectId] failed for value \"[\"1\",\"2\",\"3\"]\...
if I try to map through launchIds and convert to Mongoose.Shema.Types.ObjectId I get in the database trips: [null,null,null]
lauchIds = ['1','2','3']
async bookTrips({ launchIds }) {
let userId = "5bf7f7b3817119363da48403";
const mongoIds = launchIds.map(l => Mongoose.Schema.Types.ObjectId(l));
return this.store.User.findByIdAndUpdate(
{ _id: userId },
{
$addToSet: { trips: { $each: mongoIds } }
},
{ new: true }
);
}
Here's my model Schema:
const UserSchema = new Mongoose.Schema(
{
email: {
type: String,
required: true
},
token: String,
trips: [
{
type: Mongoose.Schema.Types.ObjectId,
ref: "trip"
}
]
},
{ timestamps: true }
);
I'm passing ids via grapql playground. Here's my mutation:
bookTrips: async (_, { launchIds }, { dataSources }) => {
console.log(launchIds);
// logs ['1','2','3']
console.log(typeof launchIds);
//Object
const results = await dataSources.userAPI.bookTrips({ launchIds });
console.log(results);
return { message: "hello" };
}
To convert a string or a number into mongo object use Mongoose.Types.ObjectId,
const mongoIds = launchIds.map(l => Mongoose.Types.ObjectId(l));
I was getting back an array of strings where this should be numbers
The solution:
My model (same as above):
const UserSchema = new Mongoose.Schema(
{
email: {
type: String,
required: true
},
token: String,
trips: [
{
type: Mongoose.Schema.Types.ObjectId,
ref: "trip"
}
]
},
{ timestamps: true }
);
crud API:
async bookTrips({ launchIds }) {
let userId = "5bf7f7b3817119363da48403";
const idsToNums = launchIds.map(Number);
const mongoIds = idsToNums.map(l => Mongoose.Types.ObjectId(l));
return this.store.User.findByIdAndUpdate(
{ _id: userId },
{
$push: { trips: { $each: mongoIds } }
},
{ new: true }
);
}
Notice the Mongoose.Schema.Types.ObjectId on model and Mongoose.Types.ObjectId on api. If I remove Schema from model or add Schema to api I'm getting an error. Not sure why, but the above example works. I hope someone will find this helpful or suggests a better solution.

MongoDB Document Validation in Meteor?

How would one approach doing this (https://docs.mongodb.com/v3.2/core/document-validation/):
db.createCollection( "contacts",
{ validator: { $or:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
]
}
} )
In this:
// database.js
import { Mongo } from 'meteor/mongo';
export const Test = new Mongo.Collection('Test');
Thanks
you first need to define your schema in meteor.
Lists.schema = new SimpleSchema({
name: {type: String},
incompleteCount: {type: Number, defaultValue: 0},
userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
This example defines a schema with a few simple rules:
We specify that the name field of a list is required and must be a
string.
We specify the incompleteCount is a number, which on insertion is
set to 0 if not otherwise specified.
We specify that the userId, which is optional, must be a string that
looks like the ID of a user document.
It’s pretty straightforward to validate a document with a schema. We can write:
const list = {
name: 'My list',
incompleteCount: 3
};
Lists.schema.validate(list);
In this case, as the list is valid according to the schema, the validate() line will run without problems. If however, we wrote:
const list = {
name: 'My list',
incompleteCount: 3,
madeUpField: 'this should not be here'
};
Lists.schema.validate(list);
Then the validate() call will throw a ValidationError which contains details about what is wrong with the list document.