Self-Join with Ember-Data - javascript

Does anyone have any suggestions on how to manually create a self-join relationship using ember-data?
If, for example, a user had many followers (other users), what would be the simplest way to build this data structure into ember-data?

Best way that we could find without going crazy was to proxy the self-join relationship with the relationship object, then just map that to the user.
So if a user has many "users" through follows then you can do:
App.User = DS.Model.extend
name: DS.attr('string')
follows: DS.hasMany('App.Follow')
followers:(->
#get('follows').map((data)-> App.User.find(data.get('followedUserId')))
).property('follows.#each')
App.Follow = Ds.Model.extend
user: DS.belongsTo('App.User')
followedUserId: DS.attr('string')
Hope that helps!

Related

How to handle many to many relationships in mongo

What is the best way to structure many-to-many models in a mongoose schema?
I have two models that have a many-to-many relationship with eachother. Users can belong to many organistaions and Organisations can have many users.
Options:
Define the relationship in each model by referencing the other model
Define the relationship in one model by referencing the other model
Option 1
const UserSchema = new Schema({
organiations: { type: Schema.Types.ObjectId, ref: "Organiation" }, // references organisation
})
mongoose.model("User", UserSchema)
const OrganiationSchema = new Schema({
users: { type: Schema.Types.ObjectId, ref: "User" }, // references users
})
mongoose.model("Organiation", OrganiationSchema)
This seems like a good idea at first and it means I can query the Organisation model to get all users and I can also query the user model to get all relative organisations.
The only problem with this is I have to maintain 2 sources of truth. If I create a organisation, I must update the user witht the orgs it belongs to and I must update the organisation with the users it has.
This leads me to option 2 which is to have one source of truth by only defining the relationship in one model.
option 2:
const UserSchema = new Schema({
organiations: { type: Schema.Types.ObjectId, ref: "Organiation" }, // references organistion
})
mongoose.model("User", UserSchema)
const OrganiationSchema = new Schema({}) // no referencces
mongoose.model("Organiation", OrganiationSchema)
This means when I create a new organisation I only need to update user with the organisations they belong to. There is no risk of the 2 sources getting out of sync. However, it does mean when it comes to querying data, it makes it more tricky. If I want to get all users that belong to an organisation, I have to query the user document. This would mean my organisation controller has to then be aware of both user and organisation models and as I start adding more relationships and models, I get tight coupling between all of these modules which I want to avoid.
How would you recommend handling many-to-many relationship in a mongoose schema?
There is no fixed solution to this.
If the organization can have orders of magnitudes more users than users can have organizations, option 2 might be a better solution.
Performance wise, populating the referenced data would be about the same as long as the referenced ids are indexed.
Having said that you might still go for option 1, even if you organization collection has the potential to have "huge" arrays. Especially if you want to make simple computation such as number of organizations users or use the "organiztion's current userIds to some other collection". In this case option 1 would be way better.
But if you opt of option 1 and if your array has the potential to become very large, consider bucket design pattern. Basically you limit the max length of your nested array. If the array reaches its max length, you make another document that holds newly added ids(or nested documents). Think of it as pagination.

createRecord with custom ID in emberjs 2.x and Firebase 3.x

Until now, I saved all my data with the following line of code:
saveUser(params) {
let newUser = this.store.createRecord('user', params);
newUser.save();
this.transitionTo('index');
This worked fine, but didn't allow for custom ID's in firebase, so I changed it into:
saveUser(params) {
let newUser = this.store.createRecord('user', {
id: params.loginId,
name: params.name,
nickname: params.nickname,
imageUrl: params.imageUrl,
email: params.email
});
newUser.save();
this.transitionTo('index');
Processes them exactly as I want them to be stored on the Firebase database, so no problem there. I'm wondering though, and not finding any solution on the web, how I can combine the two, so that I don't have to bind every param. It's bound to give problems when I add/remove model properties.
Something I'm looking for would look like this (pseudo, yes I tried it, didn't work!):
let newUser = this.store.createRecord('user', {id: params.loginId}, params);
In short, I'm looking for the dynamic properties of ('model', params), but with the option to manually adjust 1 (or more) records without having to type out all of the params.
Thanks in advance !
You will probably want to customize your serializer to accomplish this. The example in the docs is a good one, so it should be pretty straightforward: https://guides.emberjs.com/v2.13.0/models/customizing-serializers/
I am, of course, assuming you are using Ember Data for your models.

Foreign key conditions in sailsjs Waterline ORM

I have defined two models like below, what i need to do is to retrieve the unique neighborhoods that belong to active partners (partner.status=1), i can retrieve the grouped neighborhoods like this
Locations.find({groupBy: [ 'neighborhood' ],sum['id']}, function(err,locations){});
and then match against a retrieved list of active Partners or backwards (ie first getting the active partners with the locations for each partner and pushing them to an array after verifying they are not already in there) or just by a custom sql query (which i am trying to stay away from)
but... i want to know if there is some kind of way to do it with the ORM as i have seen model.find().populate('model') doesn't accept parameters beyond the desired model not the where in the find method accept foreign keys conditions.
Partner:{
attributes:{
businessName:{
type:'string'
},
status:{
type:'INT'
}
locations:{
model:'Locations'
via:'partner_id'
}
}
}
Locations:{
attributes:{
partner_id:{
model:'Partners',
type:'INT'
},
neighborhood:{
type:'STRING'
}
}
}
Thanks in advance!
Is this what you looking for?
Locations.find({where: {value1: key1}})
.populate('partners', {where: {value2: key2}})
.exec(function(err, locations){
// Now you've got what you need
});
P/S: Please checkout SailsJS v0.10.x documentation on GitHub. Personally I use this: https://github.com/balderdashy/sails-docs/tree/0.10
The documents are not up-to-date though :-)

Backbone.js singular Models not in collection

Being new to Backbone.js, just wanted to clarify the correct way to go about this simple task.
Developing a web app, almost always, you'll have user accounts, where users can login to your app, and view their personalized data. Generally, their page might show some widgets, their user information (name, avatar, etc).
Now creating a Model per widget and grouping these in a Collection is an easy concept. However, would their user info be stored in a singular Model, which would not be apart of a Collection?
If so, how is the hooked up with the rest of the app? Forgive my ignorance, but I've yet to come across any examples that don't explain Models not using them in Collections (User and Users, Dog, Cat and Animals, etc)
Anyway, sorry for the lengthly explanation. I would be looking for any resources to get me started on making a real-world app, rather than a ToDo app (which is great for the basic concept understanding)
There is not any reason to feel forced to declare a Collection for every Model your App has. It is very common to have Models without Collection associated.
// code simplified and not tested
App.CurrentUser = Backbone.Model.extend({
url: "http://myapp.com/session.json"
});
App.CurrentUserView = Backbone.View.extend({
el: "#user-info",
render: function(){
this.$el.html( "<h1>" + this.model.get( "name" ) + "</h1>" );
}
});
var currentUser = new App.CurrentUser();
currentUser.fetch();
var currentUserView = new App.CurrentUserView()({ model: currentUser });
currentUserView.render();
If you want a model / view with no collection, don't write a collection or collection view.
Add the view the same way you normally see the collection based view added.

Backbone.js nested object structure

I am working on a project where we have data models that look basically like this...
var library = {
location: 'Somewhere'
books: [
{
name: 'Good Book',
publisher: 'Great publisher'
authors: [
{
name: 'Joe Schmoe',
age: '65'
},
{
name: 'Robert Smith',
age: '47'
}
}
}
I am trying to figure out what the best way of laying out the model structure.
Something like...
var LibraryModel = Backbone.Model.extend({});
var Book = Backbone.Model.extend({});
var Books = Backbone.Collection.extend({
model: Book
});
var Author = Backbone.Model.extend({});
var Authors = Backbone.Collection.extend({
model: Author
});
Is this the best way to tackle this? Has anyone else faced anything like this?
Whether or not you need N to N, 1 to N or whatever relationships is largely a back-end concern, IMO. Unless you dealing strictly with CRUD screens, Backbone models typically don't translate directly to a back-end model, though they often approximate a back-end model.
That being said, Backbone-relational is definitely a good option for handling situations like this. It provides a very robust set of features for handling relational code and is worth looking in to.
If you'd rather stay clear of a large plugin and it's associated configuration and requirements, though, there are some simple tricks that you can use in your models directly. Since you know your data structure up front, you can make large assumptions about the code you need to write instead of having to create a very flexible system like BB-Relational.
For example, getting a list of book into a library, using the above data structure, can be as simple as:
Book = Backbone.Model.extend({});
Books = Backbone.Collection.extend({
model: Book
});
Library = Backbone.Model.extend({
initialize: function(){
this.parseBooks();
},
parseBooks: function(){
var data = this.get("books");
this.unset("books", {silent: true});
this.books = new Books(data);
}
});
I've used this code half a dozen times and it's worked out just fine for me every time. You can extend this same pattern and set of assumptions in to each layer of your object model.
You might also need to override the toJSON method on your model:
Library = Backbone.Model.extend({
// ... code from above, here
toJSON: function(){
var json = Backbone.Model.prototype.toJSON.call(this);
json.books = this.books.toJSON();
return json;
}
});
Depending on how far down this path you need to go, you will likely end up re-creating half of the functionality that BB-Relational already provides. It might be easier to use a plugin like that, with declarative relationship handling if you have a large enough structure.
IMO, it's worth understanding these basic patterns, knowing how to do this for yourself before you dig in to BB-Relational. But if you're constrained for time, I'd start with BB-Relational or some other relational mapper (I think there are a few more out there, these days).
i would not tackle this that way, because you have an N to N relationship,
1 book can have multiple authors
and 1 author has most likely written more than 1 book.
i would take a look at Backbone Relational plugin
it's not default backbone, but it does the trick the best way i can think off.
however if you only need a small solution
you can just have all your authors in a collection, and use a simple author ID array in your book model.

Categories