13

如何使用normalizr分配与实体父级相关的 id/slug ?

例子:

用户调用的 API 响应:

{
  id: '12345',
  firstName: 'John',
  images: [
    {
      url: 'https://www.domain.com/image0',
      name: 'image0'
    },
    {
      url: 'https://www.domain.com/image1',
      name: 'image1'
    }
  ]
}

我可以通过以下方式定义我的模式:

const image = new Schema('images');
const user = new Schema('users');

user.define({
  images: arrayOf(image)
})

问题是图像没有id属性,因此 normalizr 将无法区分它们,除非我们提供id属性。当然,我们可以做类似的事情

const image = new Schema('images', { idAttribute: uuid.v4() });

并生成唯一标识符。

假设我们收到用户更新并且图像的名称已更新。因为我们在每个规范化中生成唯一标识符,所以我们无法识别和更新现有图像。

我需要一种方法来引用图像实体中的父实体(用户)(在其 id/slug12345-image0中,12345-image1或作为单独的属性。

实现这一目标的最佳方法是什么?

4

2 回答 2

6

问题

以您显示的方式使用 uuid 将不起作用。

const image = new Schema('images', { idAttribute: uuid.v4() });

uuid.v4()返回一个字符串,一个可接受的值,idAttribute但现在你所有的images人都将拥有相同的 uid。不是你想要的。

理想情况下,这将起作用:

const image = new Schema('images', { idAttribute: () => uuid.v4() });

不幸的是,idAttribute将被多次调用,如本期所述。这将破坏任何实体关系。在您的示例中,图像将具有不同于用户实体引用它们的 uid。

示例输出:

users: {
  '12345': {
    id: '12345',
    firstName: 'John',
    images: [
      "cj20qq7zl00053j5ws9enz4w6",
      "cj20q44vj00053j5wauawlr4u"
    ],
  }
};
images: {
  cj20q44v100003j5wglj6c5h8: {
    url: 'https://www.example.org/image0',
    name: 'image0'
  },
  cj20q44vg00013j5whajs12ed: {
    url: 'https://www.example.org/image1',
    name: 'image1'
  }
};

解决方案

解决这个问题的方法是改变processStrategy回调中的输入值,给它一个uid属性。

const getUid = value => {
  if (!Object.prototype.hasOwnProperty.call(value, 'uid')) value.uid = uuid.v4();
  return {...value};
};

const image = new Schema('images', { processStrategy: getUid, idAttribute: 'uid'});

您现在正在改变值,这很糟糕,但该idAttribute选项使用输入值,而不是处理后的值。

或者,您可以改变idAttribute回调中的值,然后您不会将该uid字段添加到输出值。

旁注:我建议使用cuidnpm 包而不是uuid

于 2017-04-27T18:38:34.220 回答
6

idAttribute可以是接收实体、父对象和引用状态切片的键的函数:

const image = new Schema('images', {
  idAttribute: (entity, parent) => `${parent.id}-${entity.name}`
});
于 2017-02-22T21:34:40.797 回答