mongoose别名查询

793 阅读1分钟

想要实现 SQL 语句类似的查询语句 select * as x from y 别名效果的做法

下文以 给 User._id 取别名为 id 为例,说明 mongoose 的别名用法

模型定义

// 定义 Schema
// 实现方式一 使用 alias 自动生成 虚拟的 getter 及 setter 方法
export const UserSchema = new mongoose.Schema({
    _id: { type: ObjectID, auto: true, alias: "id"},
...})
// 实现方式二 使用 virtual 由于 _id: { type: ObjectID, auto: true } 在 mongoose 会自动生成,可以省略
UserSchema.virtual("id").get(function ()
{
    return this._id.toHexString();
})

查询

User.find(User.translateAliases({"id":"xx"}))
.select('id') // !!!注意这一行不能 用 {id:1,_id:0} 排除 _id,否则别名 id:undefined
.exec(...)

返回

到这一步查询结果都包含有 id 可是如果直接调用 rep.send($result) id 没有带上,以下几种方式加上 id

// 实现方式一
UserSchema.set('toJSON', { virtuals: true });
// 如果打包时候走到 toObject 方法则加上下面这句
// UserSchema.set('toObject', { virtuals: true })
// 实现方式二
// transform: function (v: any) { return v} 此方法作用是在 express 包的 rep.send($result) 时候把 id:xx 加进 json 数据,!!!注意这里是 id 不是 _id
// 也就是说查询结果没有 id:undefined, 需要在查询结果出现则必须混合 方式一 或者 方式二
export const UserSchema = new mongoose.Schema({
    id: { type: String, transform: function (v: any) { return this._id.toHexString() } },
...})

到这里返回结果还有个问题——那就是包含 _id 要用在返回结果这一步用原生的方式去掉 _id 那是不可能的!!! 具体分析:

  • 首先查询结果返回的是 model 对象不是 Obejct 用 delete 删除不行
  • model._id = undefined 也是不行的
  • 再看看 send() 之前的栈 send()>json()>stringify()>JSON.stringify()>Document.toJSON()>Document.$toObject()>clone()>cloneOvject(),这个地方有一个 specialProperties.has(k) 排除这些 ['proto', 'constructor', 'prototype'] 这是个全局配置,所以不能动. 因此在转 json 字符这条路就是死胡同! 好吧回归原始的方式
// 方式一取需要返回的值组成对象
res.send({ id: $result.id });
// 方式二直接用字符串模板
res.send(`{"id":${$result.id}}`);
// 查询结果为数组的不写了