Mongoose不会在findOne

时间:2018-01-28 20:37:50

标签: node.js mongodb mongoose

为了获得更好的存储空间并使用UUID作为主键,我自定义了_id的默认功能,以UUID的形式存储为二进制bson类型4.然后我设置了一个虚拟的id来返回_id的值。 / p>

以下是使用ES6的示例模式:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
require('mongoose-uuid2')(mongoose);
const UUID = mongoose.Types.UUID;
const uuid = require('node-uuid');
const bson = require('bson');

const schema_options = { 
    id: false,
    getters: true,
    virtuals: true,
    toObject: {
        versionKey: false,
        transform: function (doc, ret) {
            delete ret.__v;
            //delete ret._id;
        }
},
    toJSON: {
        versionKey: false,
        transform: function (doc, ret) {
          //delete ret._id;
          delete ret.__v
        }
      }  
};

const BaseSchema = new Schema (
    {
        _id: { type: UUID, default: uuid.v4, required: true },
        code: { type: String },
        name: { type: String },
        timestamps: { 
            created: {type: Date, required: true},
            updated: {type: Date, required: true}
        },
        __v: { type: Number, select: false}
    }, schema_options
);

class BaseSchemaClass {

    //virtuals
    get id() {
        return this._id;
    }

    set id(uuid_string){

        console.log(uuid_string);
        let uuid_parse = uuid.parse(uuid_string);
        console.log(uuid_parse);
        let id_buffer = new mongoose.Types.Buffer(uuid_parse);
        id_buffer.subtype(bson.Binary.SUBTYPE_UUID);
        console.log(id_buffer);
        this._id = id_buffer.toObject();
    }

    //private
    static convert_uuid_string_to_buffer (uuid_string) {

        var uuid_parse = uuid.parse(uuid_string);
        var id = new db.Types.Buffer(uuid_parse);
        id.subtype(bson.Binary.SUBTYPE_UUID);
        return id.toObject();
    }
}

BaseSchema.loadClass(BaseSchemaClass);
module.exports = BaseSchema;

架构数据似乎更新,您可以按预期读取数据。此外,似乎保存到数据库也按预期发生。

以下是一个示例记录:

{ "_id" : BinData(4,"yyfw80jURj+35wguKCKJRg=="), "timestamps" : { "updated" : ISODate("2018-01-28T19:47:05.825Z"), "created" : ISODate("2018-01-28T19:47:05.825Z") }, "code" : "MAR", "name" : "Michael", "__v" : 0 }

但是,当使用mongoose查找记录时,使用非“_id”字段时,“_ id”字段不会返回。虚拟后退_id并且未定义。

以下是使用架构的示例。

const BaseSchema = require('./schemas/base');
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
mongoose.set('debug', true);
mongoose.Promise = require("bluebird");

let db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {

    const BaseModel = mongoose.model('Base', BaseSchema);

    let base_document = new BaseModel({code: "MAR", name: "Michael", timestamps :{updated: new Date(), created: new Date() }});
    console.log(base_document.id)
    console.log(base_document.code)
    base_document.save()
    .then(() => {
      return Promise.resolve();  
    })
    .then(() => {

        return BaseModel.findOne({code: "MAR"}).exec();
    })
    .then((record) => {
        //fails
        console.log(record.id)
        console.log(record.code)
        console.log(record);
        return BaseModel.findByIdAndUpdate(record.id, { $set: { name: 'Steve', code: "STV" }});
    })
    .then(() => {

        return BaseModel.findOne({name: "Steve"}).exec();
    })
    .then((record) => {
        //fails
        console.log(record.id);
        console.log(record.code);
        console.log(record);
        db.close();
    })
    .catch((err) => {
        console.log(err);
        db.close();
    });
});

我不知道为什么_id没有在架构中返回,我尝试了查找的变体并找到了上面的更新,但它仍然没有返回_id。我在确定问题时需要一些帮助。

以下是我正在使用的npm包的版本

"bluebird": "^3.5.1",
"bson": "^1.0.4",
"mongoose": "^5.0.1",
"mongoose-uuid2": "^2.0.2",
"node-uuid": "^1.4.8"

我尝试使用节点9.2.0和8.9.4,结果相同。

我也在使用mongo 3.2

2 个答案:

答案 0 :(得分:1)

问题是mongoose-uuid2取决于mongoose 4.x,但您的包依赖项中有^5.0.1

此配置使您的包管理器安装两个不同版本的mongoose及其依赖项:代码为5.x,mongoose-uuid2为4.x.

因此,当将_id字段的二进制值转换为UUID模式类型时,mongoose-uuid2/index.js:101处的此条件的计算结果为false:

if (value instanceof mongoose.Types.Buffer.Binary)
  return value;

这是因为4.x和5.x版本中的mongoose.Types.Buffer.Binary与节点的观点不同。即使他们使用完全相同版本的mongodbbson包。

最后,它会引发"Could not cast _id to uuid."错误,并且mongoose在文档中不包含_id字段。

答案 1 :(得分:0)

在@serge的一些指导和帮助下,我找到了另一种解决方案。基本上,mongoose-uuid2(https://github.com/niahmiah/mongoose-uuid)软件包仅支持更新mongoose 4,因为版本5支持新的ES6构造,此外,由于版本1.0中bson合同中引入的更改,它仅支持bson 0.4。为了向后兼容,我理解为什么会这样。

我最终不得不创建一个mongoose-uuid2的分叉,https://github.com/thxmike/mongoose-uuid使用新的bson合约和新的mongoose api。

我已经发出拉取请求,但为了向后兼容,这可能会失败。 我不确定作者是否以及如何解决这个问题。 https://github.com/niahmiah/mongoose-uuid/pull/11

编辑: @serge:在主回购中解决了这个问题,现在可以使用Mongoose 5。 https://github.com/niahmiah/mongoose-uuid。真棒