Sails.js / waterline自引用多对多双向关联

时间:2015-09-16 16:16:10

标签: node.js sails.js waterline

我有以下类型的设置:我有一个名为Person的模型,它通过多对多关联与其他Person s(例如邻居)相关。解释是一个人可以拥有许多邻居,一个人可以成为许多其他人的邻居。模型属性看起来像这样:

...
attributes: {
    name: 'string',
    neigh: {
        collection: 'Person',
        via: 'neighOf',
        dominant: true
    },
    neighOf: {
        collection: 'Person',
        via: 'neigh'
    }
}
...

现在想象我们有两个人,A人和B人.A是B的邻居,B是A的邻居.A离开了,所以他们不再是邻居。现在,当我从A的嘶声中移除B时, A将不会自动从B 的嘶声中移除。这是一个问题。

我尝试通过为afterUpdate模型创建Person函数来解决此问题,我会检查A的neighOf字段中的每个人是否仍然拥有它们作为邻居,如果没有,将更新不再是A的邻居的Persons。我也想做相反的事情,所以如果A再次成为B的邻居(例如neigh B的字段已更新),A的neigh字段也应自动更新。这就是我想出的:

afterUpdate: function(updatedPerson, cb) {
    Person.findOne(updatedPerson.id)
        .populate('neigh')
        .populate('neighOf')
        .then(function(person) {
            updatedPerson = person;
            var ids = _.pluck(updatedPerson.neigh, 'id');
            return Person.find(ids).populate('neigh');
        })
        .then(function(people) {
            neigh_of_updated = people;
            var ids = _.pluck(updatedPerson.neighOf, 'id');
            return Person.find(ids).populate('neigh');              
        })
        .then(function(people) {
            neighOf_of_updated = people;
            var updates = [];
            _.forEach(neighOf_of_updated, function(person) {
                if (_.find(person.neigh, function(neigh) {return neigh.id === updatedPerson.id})
                    && !_.find(updatedPerson.neigh, function(neigh) {return neigh.id === person.id})) {
                    var neighIds = _.pluck(person.neigh, 'id');
                    _.remove(neighIds, function(id) {
                        return id === updatedPerson.id;
                    });
                    updates.push(Person.update(person.id, {neigh: neighIds}));
                }
            })
            return Promise.all(updates);
        })
        .then(function() {
            var updates = [];
            _.forEach(neighOfUpdated, function(person) {
                if (!_.find(person.neigh, function(neigh) { return neigh.id === updatedPerson.id; })) {
                    var neighIds = _.pluck(person.neigh, 'id');
                    neighIds.push(updatedPerson.id);
                    updates.push(Person.update({id: Person.id}, {neigh: neighIds}))
                }
            })
            return Promise.all(updates);
        })
        .then(function() {
            cb();
        })
        .catch(function(error) {
            cb(error);
        })
}

到目前为止,我还没有能够兼得。我可以让它们分开工作,但是当它们组合在一起时,代码就会无休止地循环,因为在这一切中间发生了一些更新,导致调用新的和更新的afterUpdates。

我觉得这是一个非常常见的用例,所以我猜测应该有一个更简单的方法来完成所有这些 - 或者如果没有,至少有一些方法可以使这个工作。事实上,我觉得我的头撞在一堵砖墙上应该是一件容易的事。任何人都有类似关联的经验以及如何处理它们?

0 个答案:

没有答案