mongoose $或混合字符串和_id(ObjectId)不起作用

时间:2017-06-04 09:34:32

标签: node.js mongodb mongoose

我正在尝试制作一个方法来获取一个"页面"来自查询与permalink /** * Describes methods to create, retrieve, update, and delete pages * @returns void */ function Pages() { this.pages = require('../models/pages') this.users = require('../models/users') require('mongoose').connect(require('../../config/database/mongodb').url) } /** * Retrieve a page by permalink or id * @param {string} pageQuery - id or permalink * @callback {function} cFunction */ Pages.prototype.getOne = function(pageQuery, cFunction) { this.pages.findOne({$or: [{ 'permalink': pageQuery }, { '_id': pageQuery }] }) .populate('author', 'email') .select('title permalink body author') .exec(function(error, result) { if (error) { cFunction(error) return } cFunction(result) }) } 匹配的文档库。

以下代码示例返回一个猫鼬错误:

  

'施放到ObjectId失败了值" hello-world"在路径" _id"对于模型"页面"'

现在,显然,如果案例是“hello-world”,则查询不是ObjectId。或任何其他字符串永久链接。那么我该如何使用$或者在这种情况下,还是有更明智的方法呢?

const mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId,
    pages = new Schema({
        title: { type: String },
        permalink: { type: String, unique: true },
        body: { type: String },
        author: { type: ObjectId, ref: 'users' },
        createdAt: { type: Date },
        revisedAt: { type: Date }
    })
    .index({
        title: 'text',
        permalink: 'text',
        body: 'text'
    })
    module.exports = mongoose.model('pages', pages)

页面模型

const mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId,
    users = new Schema({
        email: { type: String, unique: true },
        username: { type: String, unique: true },
        password: { type: String },
        createdAt: { type: Date }
    })
    .index({
        email: 'text',
        username: 'text'
    })
module.exports = mongoose.model('users', users)

用户模型

{{1}}

1 个答案:

答案 0 :(得分:1)

看起来如果你运行new ObjectId(pageQuery)并且它不是一个有效的ObjectId,它会抛出一个错误告诉你(即错误:传入的参数必须是一个12字节的字符串或者一个24个十六进制字符的字符串。)

在说,我会在Pages.prototype.getOne的开头使用try / catch块来尝试构建一个pageQueryOid变量,如果你到了catch块,你知道它是因为pageQuery不是有效的ObjectId。

使用此方法,您不再需要$或过滤器,但可以根据pageQuery是否为有效的ObjectId构建精确的过滤器。以下只是一个示例,但您可以更新它以满足您的需求:

Pages.prototype.getOne = function(pageQuery, cFunction) {
    var ObjectId = require('mongoose').Types.ObjectId
    var pageQueryOid
    try {
      pageQueryOid = new ObjectId(pageQuery)
    } catch(err) {
      console.log("pageQuery is not a valid ObjectId...")
    }

    var filter
    if (pageQueryOid) {
      filter = { '_id': pageQueryOid }
    } else {
      filter = { 'permalink': pageQuery }
    }

    this.pages.findOne(filter)
    .populate('author', 'email')
    .select('title permalink body author')
    .exec(function(error, result) {
        if (error) {
            cFunction(error)
            return
        }
        cFunction(result)
    })
}