For a library, I need to keep track of users and books. Basically I need to be able to know:
the list of books currently borrowed by a user
the current borrower of a given book
The app is done with node.js and mongoDB (with moogoose). I have the following schema:
BookSchema = new Schema({
title : String,
author : String,
current_borrower_email: String,
});
mongoose.model('Book', BookSchema);
// Define User model
UserSchema = new Schema({
lastname : String,
firstname : String,
email : String,
books : [BookSchema] // Books the user is borrowing
});
mongoose.model('User', UserSchema);
I guess this would be simplier to set this up in a relational DB where I could easily use many to many relation ships with foreign keys but I wanted to give a try to MongoDB.
Do you think this solution could work ? Also, if I delete a Book object, it seems I will have to remove it manually from the array of the user who borrowed it, it that right ?
In general mongodb will be good replacement of relational database for above task.
So some basics:
1.Once some one take a book you just need to copy book into the nested collection of user and user to the Book.
2.Once user has updated his profile you need aslo update information about user within Book.
3.Once book data was changed you also need update info about book within user.
4.If you trying to delete some book and current borrower exists you should say that book was borrowed by 'User' and not delete it.
I just suggest to add into your schema instead of current_borrower_email entire User object -> current_borrower: UserSchema.
So with such denormalized schema you will able easy show(within one request to mongodb):
the list of books currently borrowed by a user.
the current borrower of a given book
It is an old question but it came first in google so...
It's not too complicated but it is too long to summarize.
Read this:
http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1
Related
I am creating a Student and Course relationship
A student may have multiple courses. A one to many relationship.
This is made in Express and I'm using MongoDB. I have shorten the models to keep it simple
Student Model
const studentSchema = new mongoose.Schema({
name: {type: String},
courses: [{
type: ObjectId,
ref: 'class'
}]})
Course Model
const classSchema = new mongoose.Schema({
ClassId: {type: String,},
Grade: {type: Number,}, })
Currently, what I have is when I update the grade, it will update the grade values for the course itself and not the course in the user courses.
router.put(....)
const{username, courseId, grade} = req.params
const existingUser = await Student.findOne({username}).populate({
path: 'courses',
select:['ClassId','Grade']
})
const findCourse = existingUser.courses.find(
x => x.ClassId == courseId
)
findCourse.Grade = parseInt(grade)
await findCourse.save()
The problem is this will change the grade for the course itself. Meaning any student that adds this course will have that grade too.
I'll explain what I want to do in Java/OOP terms if that helps.
I want the student object to have it's own course objects. At the moment, it seems like classes are static class objects.
I want to access that specific student courses and change that student grade of that specific course.
Please help, I already spent a couple of hours on this. In SQL, the student would have a reference key and be able to easily change their values, I'm having trouble in MongoDB.
Alright, I finally figured it out. In hindsight, it makes sense. Gave myself a break from coding and came back to see the problem.
Lets pretend we have two students and one course. This courses is seeded with data.
When a student A picks that course, they add it to their course array. When student B wants that course, they also get that exact course. Now they are sharing the course. Basically, they are sharing the same reference.
The solution to this is to still find the course. Now make a new course object, copy every value of the original to the copy. Save the copy to the database and now you add that course to the student. Now we can still register for courses and use the seeded data and students don't share anymore.
A general parse.com relationship question really - using swift. I have a blogging app, for which there is a blog class, and a user class (along with a few others!) the blog class stores the associated user ID in a field for simplicity. Can I use includekey (or something similar) in a pfquery for the following;
firstly retrieve specific (or all) blog entries that match a criteria.
for each matching blog entry, check a field in the related user class for an option before returning the JSON list of entries
I suppose, sort of a subquery really, but wanted the whole thing to work in one pfquery if possible.
thanks!
Yes, you can do this with a relational query. The user stored in blog should be a pointer.
First create a query for the field in the user class, i.e.
userQuery.whereKey("age", greaterThan: 30)
(Do not execute this query)
Then, when adding constraints to your blog query, add
blogQuery.whereKey("user", matchesQuery: userQuery)
I am relatively new to the MongoDb world, coming from a MS Sql / Entity framework environment.
I am excited about Mongo, because of:
MongoDb's ability to dynamically change the shape of the class/table/collection at run time.
Entity framework does not offer me that.
Why is that so important?
Because I would like to create a generic inventory app and have the product class/collection/table be dynamic for clients to add fields pertinent to their business that cannot be used by everyone, eg. Vin Number, ISBN number, etc.
Now I have come to learn about Mongoose and how it offers a schema, which to me detracts from the flexibility of MongoDb described above.
I have read in a few sections that there is such an animal as mixed-schema, but that appears to be dynamic relative to the data type and not the collection of properties for the given class/collection/table.
So this is my question:
If I am looking at developing a generic class/collection /table that affords clients to shape it to include whatever fields/properties they want that pertain to their business, dynamically, should I abandon the whole notion of mongoose?
I found a benefit today as to where a Schema may be warranted:
Allow me to preface though and say I still thoroughly am excited about the whole idea that Mongo allows a collection to be reshaped at run time in circumstances where I may need ti to be. As mentioned above, a perfect example would be an Inventory app where I would want each client to add respective fields that pertain to their business as opposed to other clients, such as a Car dealership needing a VIN Number field, or a Book store needing a ISBN Number field.
Mongo will allow me to create one generic table and let the client shape it according to his own wishes for his own database at run time - SWEET!
But I discovered today where a schema would be appropo:
If in another table that will not be 're-shapeable', say a user table, I can create a Schema for pre-determined fields and make them required, as such:
var dbUserSchema = mongoose.Schema({
title: {type:String, required:'{PATH} is required!'},
FullName: {
FirstName: {type: String, required: '{PATH} is required!'},
LastName: {type: String, required: '{PATH} is required!'}
}
});
By having the respective first-name and last-name required from the schema, the database will not add any records for a user if they are not both included in the insert.
So, I guess one gets the best of both worlds: Tables that can be re-shaped and thru a schema, tables that can be rigid.
In my project, it has 3 models:
City
Plaza
Store
a city has plazas and stores; a plaza has stores.
My initial design is to use "foreign keys" for the relationship. (I am from mysql and jsut start to pick up mongodb)
class City(Document):
name = StringField()
class Plaza(Document):
name = StringField()
city = ObjectIdField()
class Store(Document):
name = StringField()
city = ObjectIDField()
plaza = ObjectIdField()
I feel this design is quite like a sql approach.
The scope of the project is like this: 5 cities; each city has 5 plazas; a plaza has 200 stores. a store has a number of products(haven't been modeled in above code)
I will query all stores in a city or in a plaza; all plazas in a city.
Should I embed all stores and plazas in City collection? I have heard do not use reference in mongodb, use embeded documents instead. In my specific projects, which one is a better approach? For me, I am comfortable with the "foreign key" design but am afraid of not taking advantage of mongodb.
From the way you described your project, it seems like an embedded approach is probably not needed - if you use indices on the city and plaza you can perform the queries you mentioned very quickly. Embedding tends to be more helpful for caching or when the embedded data doesn't make much sense on its own, and always is accessed at the same time as the parent data - not really the case here, something like addresses are a good example.
I think it makes sense to have a single collection of stores.
In each store document you could have an attribute called city, you could also have an attribute plaza. There are many other ways to structure its attributes, including more complex (subdocument) values.
If your document is:
{ storeName: "Books and Coffee",
location: "plaza 17",
city: "Anytown",
}
You can easily query for all stores in Anytown with
db.stores.find({"city":"Anytown"})
It doesn't make sense to store city and plaza in separate collections because then you will have to do multiple queries every time you need information that spans more than one collection, like store and the city it's in, or all stores in city "X".
i'm struggling with LLBLGEN and i guess ORM's in general.
i have created an entity, lets use a library example to explain:
i want to display a book object and also return a list of users who have loaned the book.
so i need to return the book object which contains a list of users.
DTO Book::
int bookId,
string bookName
additionally i wish to return with my book a collection of users who have loaned the book:
List<user> Loans
loans table might look like this:
int id
int userid
int bookid
currently my loans entity has now created this:
DTO Loans
int id
User user // user entity
Book book // book entity
im struggling to understand how this example would work in llblgen. can anyone assist with guidance or point me in the way of a tutorial?
at the moment, when i come up to update my model Book with a new loan associated to a book, im getting stackoverflow errors. i assume this is creating some sort of loop when attempting to update my Book object.
thanks
i noticed when running a profiler on SQL that the sql statement didnt include any join statements onto my relationship entities.
this was because my domain query didnt include prefetch items for my relationships, i added the following to my query:
var query = new DomainSearch<T>
{
SearchText = searchText,
PrefetchItems =
{
new Prefetch(typeof(Users))
}
};
To make sure, you are looking for a list of User entities that have loaned a particular Book entity. Is this the correct use case, or are you looking for a list of User entities that have borrowed the particular book?
Regardless, LLBLGen's support for these cases is great with referencing relationships between entities and using related entities quickly and easily.
Presuming you're looking up a book by unique BookId/ISBN/etc....
// Get the specific book entity
BookEntity book = new BookEntity(bookId);
foreach(UserEntity user in book.users)
{
// do stuff with list of users
}
It's just that simple assuming you've defined your relationships between entities.