Ember.js 余烬中双向对称关系的建模

Ember.js 余烬中双向对称关系的建模,ember.js,ember-data,Ember.js,Ember Data,假设我们有两个实体,存储在关系数据库中: 个人(身份证、姓名) 友谊(身份证、人物证、人名、实力) 在这里,我们可以看到两个人可以成为朋友,而这种友谊将被赋予一种“力量”(某种数值)。 如果1人和2人是朋友,那么我们在友谊表中有以下条目: xyz | 1 | 2 | 50 请注意,以下相应条目不存在: abc|2|1|50 每个“友谊”只创建一个条目 我要做的是如何在ember应用程序中对此进行建模。一个“人”可以有很多友谊,而一个“友谊”正好涉及两个人 // models/person.js

假设我们有两个实体,存储在关系数据库中:

个人(身份证、姓名)

友谊(身份证、人物证、人名、实力)

在这里,我们可以看到两个人可以成为朋友,而这种友谊将被赋予一种“力量”(某种数值)。 如果1人和2人是朋友,那么我们在友谊表中有以下条目:

xyz | 1 | 2 | 50

请注意,以下相应条目不存在:

abc|2|1|50

每个“友谊”只创建一个条目

我要做的是如何在ember应用程序中对此进行建模。一个“人”可以有很多友谊,而一个“友谊”正好涉及两个人

// models/person.js
DS.Model.extend({
    name: DS.attr('string'),
    friendships: DS.hasMany('friendship', {inverse: 'friends'})
});
友谊对象被序列化为

{
    id: 'abc',
    friends: ['1', '2'],
    score: '50'
}
因此:

友谊模式的实施有很多原因,让人感觉不舒服。首先,友谊没有“很多”朋友。它正好有两个。但是,如果我将实施更改为:

DS.Model.extend({
    personA: DS.belongsTo('person'),
    personB: DS.belongsTo('person'),
    ...
});
那么,我不知道如何对person=>友谊的“hasMany”关系建模。例如,“反向”字段将设置为什么

“分数”字段使事情变得复杂。如果这不存在,那么这将是“person”模型中的自反关系,但该关系有额外的数据,并且必须能够表示为自己的实体

另外,考虑到我想列出一个人的所有朋友的情况,以及这种友谊的强度,需要使用“getFriend()”函数。这个函数对我来说有点异味,我不知道为什么

所以我的问题是,你认为什么是建立双向对称关系模型的有效方法,这种关系包含额外的数据,比如“分数”字段?我无法更改数据在数据库中的存储方式,但我可以控制其他所有内容,因此我可以将数据转换为任何结构,然后从数据库转换到Ember客户端


余烬和余烬数据2.x

所以我花了一年时间,但我最终回到了这个问题上,我认为我有一个相当好的解决方案。事实上,我写了两篇博客文章详细介绍了解决方案(和),但让我在这里总结一下

该解决方案具有前端和后端组件

我将模型(在Rails中,但实际上可以是任何东西)定义如下:

# app/models/friendship.rb
class Friendship < ActiveRecord::Base
  belongs_to :friender, class_name: Person
  belongs_to :friended, class_name: Person
end

# app/models/person.rb
class Person < ActiveRecord::Base
  def friendships
    Friendship.where("friender_id = ? OR friended_id = ?", id, id);
  end
end
// app/models/person.js
import DS from 'ember-data';
import Model from 'ember-data/model';

export default Model.extend({
  name: DS.attr(),
  friendships: DS.hasMany(),
  frienderFriendships: DS.hasMany('friendship', { inverse: 'friender' }),
  friendedFriendships: DS.hasMany('friendship', { inverse: 'friended' }),
});

// app/models/friendship.js
import DS from 'ember-data';
import Model from 'ember-data/model';

export default Model.extend({
  strength: DS.attr('number'),
  friender: DS.belongsTo('person', { inverse: 'frienderFriendships' }),
  friended: DS.belongsTo('person', { inverse: 'friendedFriendships' }),
});
余烬侧的模型如下所示:

# app/models/friendship.rb
class Friendship < ActiveRecord::Base
  belongs_to :friender, class_name: Person
  belongs_to :friended, class_name: Person
end

# app/models/person.rb
class Person < ActiveRecord::Base
  def friendships
    Friendship.where("friender_id = ? OR friended_id = ?", id, id);
  end
end
// app/models/person.js
import DS from 'ember-data';
import Model from 'ember-data/model';

export default Model.extend({
  name: DS.attr(),
  friendships: DS.hasMany(),
  frienderFriendships: DS.hasMany('friendship', { inverse: 'friender' }),
  friendedFriendships: DS.hasMany('friendship', { inverse: 'friended' }),
});

// app/models/friendship.js
import DS from 'ember-data';
import Model from 'ember-data/model';

export default Model.extend({
  strength: DS.attr('number'),
  friender: DS.belongsTo('person', { inverse: 'frienderFriendships' }),
  friended: DS.belongsTo('person', { inverse: 'friendedFriendships' }),
});
在这条路线上,我将接人,并以最简单的方式展示他们的友谊:

<h2>Friends of {{model.name}}</h2>
<ul>
  {{#each model.friendships as |friendship|}}
    <li>{{friendship.friender.name}} - {{friendship.friended.name}} - {{friendship.strength}}</li>
  {{/each}}
</ul>
{{model.name}之友
    {{{#每种模式。友谊是{友谊}
  • {{友谊.友谊者.姓名}-{友谊.友谊.姓名}-{友谊.力量}
  • {{/每个}}
这是可行的,但是会向后端发送大量的xhr请求,关系的每一端(friender和friended)一个请求


通过在friendships端点的响应中使用,可以减少这些请求的数量。如果您不使用JSON API,那么肯定有一些方法可以指示哪条记录位于关系的末尾(Friendly.friender或Friendly.Friendled),这样就不需要再发出ajax请求来获取它们。

FWIW,我以前通过为关系创建单独的模型解决了这个问题。这有它自己的缺点,但它工作得很好。我已经创建了一个(Rails)API来返回双向关系。此时,它只有一个返回关系链接的
/people
端点,但它可以扩展,并且关系在ActiveRecord级别工作。哎呀,我忘记了API存储库的实际链接: