Sails.js Model: create 2 association to self failed
Asked Answered
B

1

7

I'm pretty new on Nodejs and sails. I'm implementing a server which is similiar to Twitter. In user model, there should be 2 fields: follower and following, and the 2 fields are association of the model 'user' itself.

My question is when the model have only 1 association, either follower or following, it works. However, when both follower and following included, there would be en error.

The code is something like this:

module.exports = {
   attributes: {
   alias: {
     type:'string',
     required: true,
     primaryKey: true
   },
   pwd: {
    type: 'string',
    required: true
   },
   follower: {
      collection: 'user',
      via: 'alias'
   },
   following:{
      collection: 'user',
      via: 'alias'
   }
}

The code will cause such error:

    usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/references.js:115
throw new Error('Trying to associate a collection attribute to a model tha
      ^
Error: Trying to associate a collection attribute to a model that doesn't have a Foreign Key. user is trying to reference a foreign key in user
at References.findReference (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/references.js:115:11)
at References.addKeys (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/references.js:72:22)
Bowl answered 2/5, 2015 at 3:5 Comment(3)
How are you populating your models in the controller code? If not using populateAll(), are you supplying an attribute name to populate()?Caron
@AlexAlksne I populate like this:User.find({alias:item.alias}).populate('follower').exec(console.log); Actually,I just define 'following,' even never use it. Then the sails report the error when lifing.Bowl
Odd, everything seems correct. I'm stumped so far; it's not much but if you look at the line that's causing the error in references.js it has this comment: "If no matching attributes are found, throw an error because you are trying to add a hasMany attribute to a model where the association doesn't have a foreign key matching the collection."Caron
F
3

For such usage your model definition is incorrect, namely the via keywords. As per the waterline associations docs the via keyword references the other side of the association. So, for a follower the other side is following and vice-versa. In other words:

follower: {
  collection: 'user',
  via: 'following'
},
following:{
  collection: 'user',
  via: 'follower'
}

You can check a full working example at: https://github.com/appscot/sails-orientdb/blob/master/test/integration-orientdb/tests/associations/manyToMany.selfReferencing.js

Freemanfreemartin answered 10/5, 2015 at 0:12 Comment(2)
Thanks for your example. It definitely what I need. But I think there should be the same problem in some situation. Consider there are 2 groups defined, one is guys he hates, and another is guys he love. So the model should like this: { alias: 'string' hate: { collection: 'user', via: 'alias' }, love: { collection: 'user', via: 'alias' } } It will cause the same problem, won't it? How can I avoid it?Bowl
I think you'll need to create 2 distinct self-referencing associations. One association would be loves / lovedBy and another would be hates / hatedBy. Hope that helps!Cubit

© 2022 - 2024 — McMap. All rights reserved.