Express Mongoose和ref-UUID的数组';s不能转换

Express Mongoose和ref-UUID的数组';s不能转换,express,mongoose,uuid,mongoose-schema,Express,Mongoose,Uuid,Mongoose Schema,当使用库mongoose uuid时,我能够为我的模式设置uuid类型,因此当我读取数据时,它是字符串(utf-8)格式,当我保存数据时,它是uuid ObjectID BSON type 4格式。这对于我的模式中的顶级或平面直接值和ref定义非常有效。但是,当我在模式中的ref数组中有一个UUID时,数组会正确地保存到数据库中,但是当它呈现时,它是原始类型的。根据下面的示例,您可以看到scope_id以正确的格式显示,但权利不正确 以下是我正在使用的版本: 猫鼬uuid-2.3.0 猫鼬-5.

当使用库mongoose uuid时,我能够为我的模式设置uuid类型,因此当我读取数据时,它是字符串(utf-8)格式,当我保存数据时,它是uuid ObjectID BSON type 4格式。这对于我的模式中的顶级或平面直接值和ref定义非常有效。但是,当我在模式中的ref数组中有一个UUID时,数组会正确地保存到数据库中,但是当它呈现时,它是原始类型的。根据下面的示例,您可以看到scope_id以正确的格式显示,但权利不正确

以下是我正在使用的版本: 猫鼬uuid-2.3.0 猫鼬-5.5.11

我已经尝试通过更改getter和转换值来修改库(mongoose uuid),但是,当我这样做时,它在呈现时工作,但在保存到数据库时失败。这很可能是由于值在保存到数据库之前已转换或强制转换

下面是一个示例模式

    {
      "code": {
        "type": String,
        "required": true
      }, 
      "scope_id": {
        "type": mongoose.Types.UUID,
        "ref": "scopes"
      },
      "entitlements": [{
        "type": mongoose.Types.UUID,
        "ref": "entitlements"
      }]
    }

实际响应示例

{
    "entitlements": [
        "zMihi1BKRomM1Q41p7hgLA==",
        "ztOYL7n1RoGA6aoc0TcqoQ=="
    ],
    "code": "APPUSR",
    "scope_id": "b8f80c82-8325-4ffd-bfd7-e373a90e7c45",
    "id": "32e79061-e531-45ad-b934-56811e2ad713"
}
预期反应

{
    "entitlements": [
        "ccc8a18b-504a-4689-8cd5-0e35a7b8602c",
        "ced3982f-b9f5-4681-80e9-aa1cd1372aa1"
    ],
    "code": "APPUSR",
    "scope_id": "b8f80c82-8325-4ffd-bfd7-e373a90e7c45",
    "id": "32e79061-e531-45ad-b934-56811e2ad713"
}

根据我的观察,如果您在mongoose中更改下面的函数,它可以正常工作

SchemaUUID.prototype.cast = function (value, doc, init) {
  console.log("cast", value, doc, init)

  if (value instanceof mongoose.Types.Buffer.Binary) {
    if (init) {
      return getter(value);
    } else {
      return value;
    }
  }

  if (typeof value === 'string') {
    var uuidBuffer = new mongoose.Types.Buffer(uuidParse.parse(value));

    uuidBuffer.subtype(bson.Binary.SUBTYPE_UUID);

    return uuidBuffer.toObject();
  }

  throw new Error('Could not cast ' + value + ' to UUID.');
};

基本上,当您保存对象时,
init
false
,当其启动的
init
true
时,如上所述,代码确实工作,但会破坏代码的另一部分。我找到了一个解决方案来纠正这个问题:

这是对上述守则的轻微修订

SchemaUUID.prototype.cast = function (value, doc, init) {

console.log("cast", value, doc, init)

  if (value instanceof mongoose.Types.Buffer.Binary) {
    if (init && doc instanceof mongoose.Types.Embedded) {
      return getter(value);
    }
    return value;
  }

  if (typeof value === 'string') {
    var uuidBuffer = new mongoose.Types.Buffer(uuidParse.parse(value));

    uuidBuffer.subtype(bson.Binary.SUBTYPE_UUID);

    return uuidBuffer.toObject();
  }

  throw new Error('Could not cast ' + value + ' to UUID.');
};

此代码的替代版本允许应用POST和PATCH等更新

您可以尝试mongoose-uuid2包-它可能会解决这个问题,第一个版本不太流行
mongoose-uuid2
将ID存储为字符串,而
mongoose uuid
将它们存储为二进制。二进制格式是性能所必需的,但也与文章中提到的问题有关。@jneander是正确的,mongoose uuid用于性能和存储问题。“mongoose-uuid2”在这种情况下没有帮助。我想我们是倒退了
mongoose-uuid2
使用二进制,而
mongoose-uuid
使用字符串。不过,结果是一样的。我从这个问题中得到了一些下游信息,并创建了猫鼬回购协议。似乎mongoose内部的某个地方缺少了一个部分。如果没有使用
mongoose
的解决方案,我会直接使用官方的
mongodb
节点驱动程序。在紧急情况下,您可以绕过
mongoose
,处理它无法正确执行的任何查询。用
mongoose
的方法规范化数据确实需要额外的工作。我尝试应用这种方法,但得到了相同的结果。我测试了它,然后只共享了,事实上,通过进一步的测试,我发现了问题,这是我这边的问题。您是对的,您的解决方案解决了问题。我在前面的评论中犯了错误******在附加说明中,通过更多的测试,这确实解决了问题,但现在破坏了我的补丁操作。我可以看到它通过init保存id并失败。如果你对此有一个建议,它会有所帮助。如果我必须的话,我会再发一个帖子。我建议你再发一个帖子,因为这会是另一个问题。由于某种原因,这对我来说并不起作用。doc不是嵌入的实例。它最终还是返回二进制文件。