Mongoose - insert object with array to mongo DB - arrays

I'm using Mongo for the first time and I'm having difficulties with creating a document which has an array.
The object is passed to a nodejs server like so:
{
"customerid":"121212",
"name": "Zero 2679",
"email": "a#a.com",
"address": "bla bla bla",
"tokens":[{"ctoken":"123456"},{"ctoken":"1234567"}]
}
The code executes the following:
var newCustomer = new Customer(
{
_id: request.body.customerid,
name: request.body.name,
email: request.body.email,
address: request.body.address,
tokens:request.body.tokens
});
newCustomer.save(function (err) {
if (err) winston.log('error', err);
// saved!
})
The schema is configured like so:
var customerSchema = new Schema({
// index: true => Tells mongo to index this paramater because it is used frequently. It makes querying faster
_id: {type: String, unique: true}, // unique customer ID
name: {type: String, default: '', required: true}, // Customer name
//email: {type: mongoose.SchemaTypes.Email, required: true},
email: {type: String, required: true},
address: { type: String, required: true },
toknes: [{ ctoken :{type: String} }]
}, {collection: 'customers'});
When I go and look at the object in the MongoDB, it looks like this:
{
"_id": "121212",
"email": "a#a.com",
"address": "bla bla bla",
"tokens": [],
"name": "Zero 2679",
"__v": 0
}
The tokens are missing and there's a '_v' value which I don't even have.
Please advise what am I doing wrong?

in your schema
tokens: [{ ctoken : String }]
request.body.tokens must be something like = {ctoken: 'some string'}
var newCustomer = new Customer(
{
_id: request.body.customerid,
name: request.body.name,
email: request.body.email,
address: request.body.address,
tokens:[request.body.tokens]
});
newCustomer.save(function (err) {
if (err) winston.log('error', err);
// saved!
})
and if the customer db documents contains data, then you should perform push operation

In your schema it should be:
tokens: [{ type: String }]
As ctoken is not a data type. The working schema is illustrated below:
var customerSchema = new Schema({
_id: {type: String, unique: true},
name: {type: String, default: '', required: true},
email: {type: String, required: true},
address: { type: String, required: true },
tokens: [{ type: String }]
}, {collection: 'customers'});

Related

Why is my mongoose populate query throwing "Cannot populate path because it is not in your schema" error?

I'm building a form management program but right now I'm just trying to build a queue system to handle all the forms when they're assigned to someone.
when I call this first function, it should populate the elements of the activeWork array by pulling from each collection that the entries reference, there are several collections that could be referenced in active work, so I'm trying to use the collection type field to determine what collection to pull from, I don't know if I formatted any of this correctly because its my first time building any of this.
import statesPersons from "./statesPersons.schema.js";
export async function getStatesPersonsActiveWorkByProfileId(req, res){
try{
const { profileId } = req.params
const data = await statesPersons.find({profileId})
.populate('statesPersons.activeWork.referenceId')
return res.send({
message: "success",
data: data,
status: 200 })
}catch(e) {
console.error(e.message)
return res.send({
message: "couldn't fetch active work",
data: null,
status: 500 })
}
}
Here is the schema for statesPersons, the collection where active work is stored.
import mongoose, {model, Schema} from "mongoose";
const activeWorkSchema = new Schema({
active: Boolean,
collectionType: {
type: String,
enum: ['messages'],
},
referenceId: {
type: Schema.Types.ObjectId,
refPath: "statesPersons.activeWork.collectionType"
},
sentBy: {
type: Schema.Types.String,
ref: "statesPerson",
},
sentTo: {
type: Schema.Types.String,
ref: "statesPerson",
},
timeRecived: Date,
dueDate: Date,
subject: String,
viewed: Boolean,
content: {},
})
const statesPersonsSchema = new Schema({
profileId:{
type: String,
required: true,
unique: true
},
department: {
type: String,
required: true,
index: true,
},
firstName: String,
lastName: String,
location: String,
org: String,
title: String,
jobDescription: String,
email: {
type: String,
lowercase: true,
},
phoneNumber: String,
activeWork: [activeWorkSchema],
emailList: [String],
jobAssignments: [String],
affiantInfo: {
affiantInfoTitle: String,
affiantInfoExperience: String,
},
assessments: [
{
assessdBy: {
type: Schema.Types.ObjectId,
ref: "statesPerson",
},
dueDate: Date,
questions: {},
},
],
});
export default mongoose.model("statesPersons", statesPersonsSchema);
When I make a query, I get:
Cannot populate path statesPersons.activeWork.referenceId because it is not in your schema. Set the strictPopulate option to false to override.
I don't know if I formatted my populate correctly or if the problem is in my schema,

How do I accept an array of strings using Apollo Server and GQL?

I currently have a typeDefs file that has a custom Books type. This is how it looks at the moment:
type: Books {
bookId: String
authors: [String]
description: String
title: String
}
I am using MongoDB in order to store my data. My model looks like this:
const bookSchema = new Schema({
authors: [
{
type: String,
},
],
description: {
type: String,
required: true,
},
// saved book id from GoogleBooks
bookId: {
type: String,
required: true,
},
title: {
type: String,
required: true,
}
});
And my resolvers look like this:
saveBook: async (parent, args, context) => {
if (context.user) {
const book = await Book.create({ ...args })
await User.findByIdAndUpdate(
{ _id: context.user._id },
{ $addToSet: { savedBooks: { bookId: args.bookId } } },
{ new: true }
);
return book;
}
throw new AuthenticationError('You need to be logged in!');
},
When I use graphql playground and send data in the query variable I am getting an error that String cannot represent a non string value: [\"james\", \"jameson\"]", when I send
{
"input": {
"bookId": "1",
"authors": ["james", "jameson"],
"description": "thdfkdaslkfdklsaf",
"title": "fdjsalkfj;a",
}
}
I know that it is because I am using an array of strings and entering an array of strings to gql will result in this error. I thought that if I put brackets around the String in my typeDefs it would work just find. I can't seem to find a way to send an array of strings to gql. I looked through the documentation and can't find a way to complete this..
Make a typedef out of author and then give the author variable within books the type "Author".
I think you also have to define the array in the bookschema if I'm not incorrect.
And don't forget to make sure the model naming in your database has to be the same as in your code.
Like this:
type: Author {
name: String
}
type: Books {
bookId: String
authors: [Author]
description: String
title: String
}
const bookSchema = new Schema({
authors: [
{
type: Author,
},
],
description: {
type: String,
required: true,
},
// saved book id from GoogleBooks
bookId: {
type: String,
required: true,
},
title: {
type: String,
required: true,
}
});
Hope this works :)

How to save nested array of objects data using mongoose?

So, I'm sending data from angular reactive form like:
Angular reactive form UI image
and
Data being sent to backend in browser console image
I have made schema for task as:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let taskSchema = new Schema({
taskId:{
type:String,
unique:true
},
task:{
type:String,
default:''
},
subTask:[{
type: Schema.Types.ObjectId,
ref: 'SubTask'
}]
}
module.exports = mongoose.model('Task',taskSchema);
Schema for Sub-Task as:
let subTaskSchema = new Schema({
title:String,
subSubTask:[{
type: Schema.Types.ObjectId,
ref: 'SubSubTask'
}]
})
module.exports = mongoose.model('SubTask',subTaskSchema);
Schema for Sub-Sub-Task as:
let subSubTaskSchema = new Schema({
title:String
})
module.exports = mongoose.model('SubSubTask',subSubTaskSchema);
Now,I'm confused about how to save nested array of objects data in mongodb using mongoose?
you can define your schema like this
const userSchema = new mongoose.Schema({
likedBooks: [{
type: mongoose.Types.ObjectId,
ref: 'books'
}],
email: {
type: String,
required: true
},
name: {
type: String,
required: true
}
});
exports.User = mongoose.model('users', userSchema);
then you can populate data by doing
user = User.find({ email: req.body.email }).populate('likedBooks');
here likedBooks contains _id of each book
const bookSchema = new mongoose.Schema({
isbn: {
type: Number,
required: true
},
name: {
type: String,
required: true
},
author: {
type: String,
required: true
},
publisher: {
type: String,
default: ""
},
imageUrl: {
type: String,
required: true
},
description: {
type: String,
default: ""
}
});
exports.Book = mongoose.model('books', bookSchema);
for both schema i have not put _id as it is auto generated by mongodb and it is used as reference
The Object Model should look like this before saving.
{
taskId: 1,
task: 'Do something',
subTask: [{
title: 'Write a essay',
subSubTask: [{
title: 'Collect details to write an essay'
}]
}]
}
Hope it helps...

Save current User into field within array in Mongoose

Here is a relevant part of my Schema, where I'll make reservations to a "space":
var spaceSchema = new mongoose.Schema({
spaceName: String,
scheduledDates: [{
scheduledDates: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
username: String
}
}]
});
Author should be the current user that's logged in. Here is my route to update those fields:
router.put('/:space_id/schedule', function(req, res) {
Space.findByIdAndUpdate(req.params.space_id, {
'$push': { 'scheduledDates': req.body.space, 'author': req.user._id }
}, { "new": true, "upsert": true }, function(err, space) {
if (err) {
console.log(err);
} else {
console.log(req.body.space);
}
});
});
I can't access "author" correctly, because it's inside the array. What can I do to update this array, adding a new date and user to make the reservation?
Thank you
UPDATE
I tried to use "_id" instead of "id" in my property but got the same result. It seems like it's ignoring the "author" field, and only saving "scheduledDates"
So the schema was like this:
scheduledDates: [{
scheduledDates: String,
author: {
_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
username: String
}
}]
And then in my route, I changed what I was 'pushing':
'$push': { 'scheduledDates': req.body.space, 'author._id': req.user._id }
UPDATED 2
Changed the way I was getting the object to push:
'$push': {
'scheduledDates': {
'scheduledDates': req.body.space,
'author': { _id: req.user._id, username: req.user.username }
}
}
Now I'm getting the following error:
message: 'Cast to string failed for value "{ scheduledDates: \'04/11/2017\' }" at path "scheduledDates"',
name: 'CastError',
stringValue: '"{ scheduledDates: \'04/11/2017\' }"',
kind: 'string',
value: [Object],
path: 'scheduledDates',
reason: undefined } } }

Mongoose: Update by pushing an object in an array

This is the model I am working with:
name: {
type: String
},
payment: {
id: {
type: String,
required: true
},
cards: [
{
id: {
type: String
},
is_default: {
type: Boolean,
"default": false
}
}
]
}
I want to add a card to the cards array, for example:
card =
id: "some_token"
is_default: true
I am using the update method to push the card to the array, but it won't add the card to the document. Instead, it creates a new document with only those fields:
{
id: "some_token",
is_default: true,
_id: someId
}
Any idea how I can update the actual document I am targeting instead of creating a new document?
Here's my code (using CoffeeScript):
update_where =
payment:
id: "some_id"
update_push =
$push:
'payment.cards':
id: card_token
is_default: false
Customer.update update_where, update_push, {upsert: true}, (err, results) ->
# Do something with the results
Oh… I just noticed my mistake. The problem was in the where statement.
I was doing:
payment:
id: "some_id"
But the right thing to write is the following:
'payment.id': 'some_id'
And it now works!

Resources