DynamoDB one-to-many - nosql

I have read that DynamoDB can use sortkey to add items to a specific primary key. Coming from a world of SQL, I have a hard time understanding this concept.
Let's say we have the following: A user with a profile, many items and many family members.
Should I create just ONE table with e.g. a user id, and different sortkeys for the relevant information?
Like:
pk: userId, sk: ITEMS#{id:1, type: bottle}
pk: userId, sk: PROFILE#{id: 1, username: "Bill Gates"}
pk: userId, sk: FAMILYMEMBERS#{[{id:1, name: "mom"}, {id: 2, name: "dad"}]}
For me, the sk should be connected to another table (but that may be what we want to avoid with nosql design).
Like:
pk: userId, sk: [matchingItemsWithUserId]
Should I store everything in one object? And what about the attributes? Should the come from a table, or inserted as a json object?

Related

Want to change a model ObjectID value

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.

How to delete record in m-m table

Have two entities Book and Genre, which have relations M-M = BookGenre.
BookGenre has two attributes BookId, GenreId. They are represented like foreign key, however they could be null.
SO! The question is, if i want to delete for Book specific GenreId, the record in this table will look like:
BookId Genre
1 null
Which looks so odd. And now, i'm looking for the solution to delete this thing, how is it possible?
Try this. It will remove the whole records from BookGenre table. But Book and Genre records will remain in DB.
var booksToRemove= _dbContext.Set<BookGenre>().Where(i=> i.GenreId==1).ToArray();
_dbContext.Set<BookGenre>().RemoveRange(booksToRemove);
_dbContext.SaveChanges();

Unsure how to model many-to-many relationship in MongoDB

I'm new to MongoDB and I'm trying to model a Many to Many relationship into at least 2 collections (I need two collections for the project). What I'm having is a collection of universities, faculties and specializations, and another collection for students and their gradebook (this was the middle entity between specializations and students in SQL, not sure if it's needed in Mongo anymore). I tried to use This as an inspiration but it limits me as I can only search students by university id (I want for example to search students from a certain specialization or a certain faculty). I could put every row from university, faculty and specialization in the student collection and vice versa but I really don't think it's ideal. Here's what I have so far:
db.students.insertOne({_id:1, firstname: 'John', lastname: 'Silas', ethnicity:'english', civilstatus:'single', residence:'London', email:'johnSilas#gmail.com', gradebook:[{ year:2018, registrationyear:2017, formofeducation:'traditional'}], universities:[1]})
db.universities.insertOne({_id:1, name:'University of London', city:'London', adress:'whatever', phone: 'whatever', email: 'whatever#gmail.com', faculty:[{name: 'Law', adress:'whatever', phone: 'whatever', email: 'whatever#gmail.com'}], specialization:[{name:'criminal rights', yearlytax:5000, duration: 3, level:'bachelordegree', language:'english'}], students: [1,2]})
I'm sorry if I don't understand basic noSQL concepts, I am new to it. Thanks in advance.
Basic patterns for many to many association between A and B:
Inline references
On A, store the list of B ids in a field like b_ids
On B, store the list of A ids in a field like a_ids
This requires two writes whenever an association is created or destroyed, but requires either zero or one joins at query time to traverse the association (if you just want the id of Bs for a given A and you have the A already no further queries are needed).
Join model
Create a model C which has two fields: a_id and b_id. Each association is represented by a single instance of C.
This requires one write whenever an association is created or destroyed, but requires joins on all queries involving association (potentially two joins per query).

Implementing 3 way relationship in Prisma

I also asked this question on Prisma forum.
** EDIT **: The forum has since been locked as read-only just 1 day after my question. It's sure getting scary because there is no official announcement of whether they'll stop developing Prisma 1 after implementing promised features or not. Surely they could have said something. And TBH, the unstable Prisma site does add to my shaking confidence in Prisma despite the number of stars in their repo.
I'm new to Prisma. So I have a 3-way relationship between User, Event and Role I would like to define. For each association of a User and an Event, there exists a Role for that association. If I were to design a database table for another ORM, I would have created a event_user table with user_id, event_id and role_id as columns to relate them.
Practically, a row of these 3 columns must be unique. Obviously, it would be good if Prisma can do the safeguarding of these constraints, but the obvious solution I see might not even come to Prisma 1.
My current design consists of the following:
type User {
// ...
eventUsers: [EventUser!]!
}
type Event {
// ...
eventUsers: [EventUser!]!
}
type EventUser {
role: Role!
event: Event!
user: User!
}
This design will make render all xxWhereUniquexx unusable, which is definitely a hassle to maintain relationships. upserts will certainly be unusable for maintaining the relationships.
How would one create a relationship like this in Prisma?
For some context, each user would have a list of global roles as well, so there would already be an association between User and Role. The question concerns the "local roles" for each event.
If each user already have a value for their respective roles, there would be no need for a third table (unless there is more information you'd like to be stored in your modal layer in which case the role type should be in the Role table).
Relationships are set with the #relation directive. You can apply it to either one of two tables in a relation but for clarity I'm apply them to the Event table. The example assumes users can be part of several events.
Tables:
enum ROLE_TYPE {
TYPE_ONE
TYPE_TWO
}
User {
user_id: ID! #id
events: [Event!]!
}
Event {
event_id: ID! #id
users: [User!]! #relation(link: INLINE)
}
Role {
role_id: ID! #id
type: ROLE_TYPE
event: Event! #relation(link: INLINE)
user: User! #relation(link: INLINE)
}
You can read more about relations on the Prisma site

DynamoDB modeling relational data (restaurant menus example)

I'm creating a web platform on AWS to enable restaurant owners in my community to create menus. I'm moving from a relational database model to a NoSQL solution and wondering the best way to organize this data. My current relational model is as follows:
Table 'restaurants': id (int / primary key), name, owner (int)
Table 'categories': id (int / primary key), restaurant (int), parent (int)
Table 'items': id (primary key), name, category (int)
Only the owner should be allowed to create/update/delete places, categories, and items.
What would you recommend as a de-normalized solution given the ownership constraint? I was thinking of doing the following:
Table 'restaurants': id (primary key), owner (sort key), categories (list of ids)
Table 'categories': id (primary key), restaurant (id), items (list of item objects), subcategories (list of category ids)
Wondering if it'd be better to have all category data contained within the restaurant table. As an example, a user should only be able to add an item to a category if they are the owner of the associated restaurant, which would take an additional query, per above.
Depends mostly how you use your data . If usually the Restaurant is read full, is ok to have all in the restaurants table.
If you have a lot of operations only on one category , for example many are interested only in food and not interested in drinks , then it would be good to have this done on categories.
I think for some restaurants would be better to have it split in categories and keep common data on restaurant level , address, phone , opening hours and so on .
I don't think write is important , seems to be over 90% read web site.0
Perhaps a cache solution ? Redis ? Memcache ? this would speed up even more.