合并多对一的对象列表

Merge many-to-one list of objects

我目前有两个数据库table,代表多对一的关系。具有 ID(整数、自动增量、主键)和名称(varchar(255),非空)的活动;和 ActivitySlugs,它们有一个 ID(与上面相同)、一个 slugname(不是 null varchar)和一个 activity_id(Activities.id 的外键)。

目前我应该获得所有活动及其所有 slug 的列表(作为一个列表),因此它看起来像这样:

[
    {id: 1, name: "long name", slugs: ["nick", "names"]},
    {id: 2, name: "foobar", slugs: ["foo", "bar"]}
]

天真的解决方案(也是我能想到的唯一一个)是对每个 table 执行 "SELECT *",然后合并它们,但我得到的数据看起来像这样:

activities = [
    {id: 1, name: "long name"},
    {id: 2, name: "foobar"}
]
slugs = [
    {id: 1, slugname: "nick", activity_id: 1},
    {id: 2, slugname: "names", activity_id: 1},
    {id: 3, slugname: "foo", activity_id: 2},
    {id: 4, slugname: "bar", activity_id: 2}
]

然后我可以遍历两者并添加它们:

activities.forEach(function(activity) {
    slugs = [];
    activitySlugs.forEach(function(slug) {
        if (slug.activity_id == activity.id) {
            slugs.push(slug.name);
        }
    });
    activity.slugs = slugs;
);

这感觉笨拙、缓慢且不精炼。它肯定不会扩展。不幸的是,我似乎找不到更好的方法让它们与这样的数组进行多对一合并。

由于 slug 只能属于一个 activity,因此您应该遍历 slug 并附加到某个 activity 对象。

var activities = [
    {id: 1, name: "long name"},
    {id: 2, name: "foobar"}
];
var slugs = [
    {id: 1, slugname: "nick", activity_id: 1},
    {id: 2, slugname: "names", activity_id: 1},
    {id: 3, slugname: "foo", activity_id: 2},
    {id: 4, slugname: "bar", activity_id: 2}
];

slugs.forEach(function(slug) {
    var a = activities.filter(function(a){return a.id==slug.activity_id;}); 
    // should check if it exists - assume that it does
    if (a[0].slugs == undefined) {
      a[0].slugs = [slug.id];
    } else {
      a[0].slugs.push(slug.id);
    }
});

您可以构造一个 id2activity 映射以通过其 id 访问任何 activity:

var id2activity = {};
activities.forEach(function(activity) {
    activity.slugs = [];
    id2activity[activity.id] = activity;
);

activitySlugs.forEach(function(slug) {
    id2activity[slug.activity_id].slugs.push(slug.name);
});