OneToOne relationship with ember-model - ember-model

How to implement a one to one relationship with ember-model ?
I have tried the following code but it does not work.
App.Book = Ember.Model.extend({
id: Ember.attr(),
title: Ember.attr(),
name: Ember.attr(),
author: App.Author
});
App.Author = Ember.Model.extend({
id: Ember.attr(),
firstName: Ember.attr(),
lastName: Ember.attr()
});
I have also tried the next code but I get an error when I try to set the author with the next code:
Error: You must use Ember.set() to access this property (of )
var book = App.Book.create({
author: App.Author.create({firstName: 'fred'})
});
App.Book = Ember.Model.extend({
id: Ember.attr(),
title: Ember.attr(),
name: Ember.attr(),
author: Ember.attr(App.Author)
});
I'm using the RESTAdapter and my JSON looks like:
{title: 'booktitle', name: 'thename', author: {firstName: 'fred', lastName: 'last'}}

Try this:
author: Ember.belongsTo('App.Author', {embedded: true})
If that doesn't work try:
author: Ember.belongsTo('App.Author', { key: 'author', embedded: true})

Related

Why .populate returns [model] and not the content of the collection

I'm learning mongoose, and I have the below code where I create an Author and a Course and I reference the Author in a Course model.
const Course = mongoose.model(
"Course",
new mongoose.Schema({
name: String,
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "Author",
},
})
);
const Author = mongoose.model(
"Author",
new mongoose.Schema({
name: String,
bio: String,
website: String,
})
);
Then I try to list all the courses and populate the author prop but I just get author: [model] instead of the contents.
async function listCourses() {
/* Use the populate method to get the whole author,
and not just the id.
The first arg is the path to the given prop
i.e. author: {
type: mongoose.Schema.Types.ObjectId,
ref: "Author",
},
We can populate multiple props ...
*/
const courses = await Course.find()
.populate('author')
// .populate({ path: "author", model: Author })
// .populate("author", "name -_id")
// .populate('category')
.select("name author");
console.log(courses);
}
I tried several ways to get the content. I also tried some solutions from this question, but nothing worked.
This is the log I get:
_doc: {
_id: 632c00981186461909cebb20,
name: 'Node Course',
author: [model]
},
I checked the docs to see if the way I'm trying is deprecated, but they have the same code as here.
So how can I see the content?
Thanks!
After all, it was a "wrong" logging approach. By iterating over the array of courses and accessing the author prop, the content was revealed.
This is the modified log, in the listCourses function;
console.log(courses.map((c) => c._doc.author));
And this is the output:
isNew: false,
errors: undefined,
_doc: {
_id: 632bfd0c7f727d15fcd3f712,
name: 'Mosh',
bio: 'My bio',
website: 'My Website',
__v: 0
},

References in another Schema - mongoose

I'm doing some tests with MongoDB and NodeJS for a new project.
Searching the documentation I found that it is possible to make references to other collections and bring this data to JSON.
It was then that I decided to perform the following test:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const userSchema = new Schema({
name: {
type: String,
required: true,
unique: true
},
email: {
type: String,
required: true,
unique: true,
},
posts: [{
type: Schema.Types.ObjectId,
ref: 'Post'
}]
})
const userModel = mongoose.model('User', userSchema)
const postSchema = new Schema({
title: {
type: String
},
content: {
type: String
},
author: {
type: Schema.Types.ObjectId,
ref: 'User'
}
})
const postModel = mongoose.model('Post', postSchema)
const saveUser = new userModel({
name: 'user',
email: 'user#email.com'
})
saveUser.save()
const savePost = new postModel({
title: 'Lorem',
content: 'Lorem Ipsum',
author: saveUser._id
})
savePost.save()
postModel.find()
.populate('User')
.exec((err, post) => {
console.log(post)
})
However the return of JSON is:
{
_id: 5edd0c24a4f42b0e126f4b15,
title: 'Lorem',
content: 'Lorem Ipsum',
author: 5edd0c24a4f42b0e126f4b14,
__v: 0
}
When should it be:
{
_id: 5edd0c24a4f42b0e126f4b15,
title: 'Lorem',
content: 'Lorem Ipsum',
author: {
_id: 5edd0c24a4f42b0e126f4b14,
name: user,
email: user#email.com
},
__v: 0
}
Does anyone know any solution to this problem where I can insert for all my new Schemas?
Regarding populate you should provide the field name provided in postSchema. So should replace .populate('User') with .populate('author').
Since the post requires the author _id you should save the post only after the author is successfully saved
const saveUser = new userModel({
name: "user",
email: "user#email.com",
});
saveUser.save((err, data) => {
if (err) console.log(err);
else {
const savePost = new postModel({
title: "Lorem",
content: "Lorem Ipsum",
author: saveUser._id,
});
savePost.save();
}
});

Mongoose: query one to many relationship, but inverse

I am doing an app with MongoDB/Mongoose/Node.js RESTapi.
I have two models: Books and Authors.
An Author can write many books. Only a book can be written by an author.
The models are defined like this.
author model
var authorSchema = new Schema({
name: {type: String, required: true},
surname: {type: String, required: true},
book model
var bookSchema = new Schema({
isbn: {type: String, required: true},
title: {type: String, required: true},
author: {type: Schema.Types.ObjectId, ref: 'Author'},
description: {type: String}
What I am trying to do, is get the books that were written by an author. This is my API endpoint. IdAuthor is the id that mongodb gives.
on books-routes.js
localhost:3000/api/book/author/:idAuthor
router.get('/author/:idAuthor', (req, res, next) => {
let idAuthor = req.params.idAuthor;
Book.find({ author: idAuthor })
.select('isbn title author description')
.exec()
.then(bookCollection => {
const response = {
count: bookCollection.length,
books: bookCollection
}
if (response.count) {
res.status(200).json(bookCollection);
} else {
res.status(200).json({
message: 'This author does not have any book'
});
}
})
.catch(err => {
res.status(500).json({
error: err
});
});
});
Sadly, it is allways returning an empty array of books. I am sure it has something to do about "author" attribute referencing to the authors model.
I have also tried doing this:
Book.find({ author: ObjectId(idAuthor) })
without luck.
Thank you for your help!

How to insert data in to related mongoose Schemas?

I am trying to create an api endpoint in nodejs to insert data in mongodb. I have got two mongoose schemas which are related to each other that`s why i am relating these two schemas like below:
Posts schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PostSchema = mongoose.Schema({
title: { type: String, trim: true, required: true},
description: { type:String, required: true },
created_at: { type: Date, default: Date.now },
author: {type: Schema.ObjectId, ref: 'Author', required: true},
});
const Post = module.exports = mongoose.model('Post', PostSchema);
Authors Schema:
const mongoose = require('mongoose');
const AuthorSchema = mongoose.Schema({
fullname: { type: String, trim: true, required: true},
address: { type: String, required: true },
phone: { type: Number, required: true },
email: { type: String, required: true },
created_at: { type: Date, default: Date.now }
});
const Author = module.exports = mongoose.model('Author', AuthorSchema);
Now i can easily insert data for authors schema
Authors.js:
router.post('/', (req, res, next) => {
let newAuthor = new Authors({
fullname: req.body.fullname,
address: req.body.address,
phone: req.body.phone,
email: req.body.email
});
newAuthor.save((err, user) => {
if(err) {
res.json({
success: false,
msg: "Failed to add author"
});
} else {
res.json({
success: true,
msg: "Author added successfully"
});
}
});
});
But for posts i am stuck in here
posts.js:
router.post('/', (req, res) => {
var newPost = new Posts({
title: req.body.title,
description: req.body.description,
author:
})
})
main problem is how to get author??
You can set author id in author field.
// you can set authorId in req.body and use that
router.post('/', (req, res) => {
var newPost = new Posts({
title: req.body.title,
description: req.body.description,
author: req.body.authorId
})
});
OR you can set author id in route path and use req.params.authorId
// for that route from ui call should be like
// var userId = 4654654545454
// $http.post('/'+userId)....
router.post('/:authorId', (req, res) => {
var newPost = new Posts({
title: req.body.title,
description: req.body.description,
author: req.params.authorId
})
});
On the page where you allow users to create posts, you need to pass the author's id along with the rest of the post details. Then you can simply refer to the author's id by whatever you chose to send it as (i.e. authorId).
If you are using a serializer that takes all the values from your form and nicely packages them, then insert a hidden input field that stores the author's id, so you can capture that as well. For example:
<input type="hidden" name="authorId" value={user._id} />
Otherwise, if you are manually packaging the form field values, then just add the author's id as another property in the response object. Not sure what you're doing to send the request but say you were using the axios library to send an ajax post to your endpoint you could do this to easily add the author to the response:
const title = document.getElementByNames("title")[0].value
const description = document.getElementByNames("description")[0].value
const author = document.getElementByNames("authorId")[0].value
axios.post("/posts", {title: title, description: description, author: authorId}).then(res => console.log(res))

MongoDB & Mongoose: Can mongoose map referenced documents before referenced document is created?

I think my post title is a bit nebulous. Let me clarify.
I have the following schemas:
var listSchema = mongoose.Schema({
_owner: { type:ObjectId, ref: 'User' },
title: String,
description: String,
creation_date: { type: Date, default: Date.now }
});
var taskSchema = mongoose.Schema({
_taskList: { type: ObjectId, ref: 'List' },
title: String,
description: String,
creation_date: { type: Date, default: Date.now }
});
var List = mongoose.model('List', listSchema);
var Task = mongoose.model('Task', taskSchema);
Each 'Task' references a 'List'. Is it possible to save a new 'Task' referencing a 'List' that does not already exist in the collection? For example:
//assume I have a user.id
var NewList = new List({
_owner: user._id,
title: 'Test List',
description: 'List Description'
});
var NewTask = new Task({
_taskList : NewList, //ref to the document above (_id not created yet)
title: 'Task Title',
description: 'Task Description'
});
NewTask.save(function(err, task){
...
});
Is something like this possible or do I need to save the List then save the Task?
Thanks a lot!
Mongoose actually creates the _id value for a new doc client-side, so you have access to the _id for NewList even before you save it.
So you can simply do:
var NewTask = new Task({
_taskList : NewList._id,
title: 'Task Title',
description: 'Task Description'
});

Resources