MongoDB - 按 ID 或其他字段查找条目

MongoDB - Find entry either by ID or by other field

我正在使用 MongoDB 和 Mongoose 编写 Node.JS 应用程序。我遇到的问题之一是我需要通过 ObjectIDurl 字段找到元素。我试着这样写:

const mongoose = require('mongoose');
const ObjectID = mongoose.Types.ObjectId;

Event
  .findOne({ $or: [
    { _id: new ObjectID('hello) },
    { url: 'hello },
  ] })
  // doing domething with the result

但是如果字符串不是有效的ObjectID,程序会崩溃,说它不是有效的ObjectID字符串:

Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
        at new ObjectID (/usr/app/oms-events/node_modules/bson/lib/bson/objectid.js:34:11)
        at Server.exports.fetchSingleEvent (/usr/app/oms-events/lib/middlewares.js:178:14)
        at next (/usr/app/oms-events/node_modules/restify/lib/server.js:912:30)
        at f (/usr/app/oms-events/node_modules/once/once.js:25:25)
        at Request.httprequest [as _callback] (/usr/app/oms-events/lib/middlewares.js:165:14)
        at Request.self.callback (/usr/app/oms-events/node_modules/request/request.js:186:22)
        at emitTwo (events.js:106:13)
        at Request.emit (events.js:191:7)
        at Request.<anonymous> (/usr/app/oms-events/node_modules/request/request.js:1081:10)
        at emitOne (events.js:96:13)
        at Request.emit (events.js:188:7)
        at IncomingMessage.<anonymous> (/usr/app/oms-events/node_modules/request/request.js:1001:12)
        at IncomingMessage.g (events.js:292:16)
        at emitNone (events.js:91:20)
        at IncomingMessage.emit (events.js:185:7)
        at endReadableNT (_stream_readable.js:974:12)
Program node /usr/app/oms-events/lib/server.js exited with code 1

如果我将删除到 ObjectID 的转换,如下所示:

Event
    .findOne({ $or: [
      { _id: 'hello' },
      { url: 'hello' },
    ] })

它也会因 CastError:

而崩溃
{ MongooseError: Cast to ObjectId failed for value "hello" at path "_id"
  at CastError (/usr/app/oms-events/node_modules/mongoose/lib/error/cast.js:26:11)
  at ObjectId.cast (/usr/app/oms-events/node_modules/mongoose/lib/schema/objectid.js:147:13)
  at ObjectId.castForQuery (/usr/app/oms-events/node_modules/mongoose/lib/schema/objectid.js:187:15)
  at cast (/usr/app/oms-events/node_modules/mongoose/lib/cast.js:218:32)
  at cast (/usr/app/oms-events/node_modules/mongoose/lib/cast.js:36:18)
  at model.Query.Query.cast (/usr/app/oms-events/node_modules/mongoose/lib/query.js:2741:10)
  at model.Query.Query.findOne (/usr/app/oms-events/node_modules/mongoose/lib/query.js:1354:10)
  at /usr/app/oms-events/node_modules/mongoose/lib/query.js:2300:21
  at model.Query.exec (/usr/app/oms-events/node_modules/mongoose/lib/query.js:2294:17)
  at Server.exports.fetchSingleEvent (/usr/app/oms-events/lib/middlewares.js:182:6)
  at next (/usr/app/oms-events/node_modules/restify/lib/server.js:912:30)
  at f (/usr/app/oms-events/node_modules/once/once.js:25:25)
  at Server.exports.fetchUserDetails (/usr/app/oms-events/lib/middlewares.js:92:12)
  at next (/usr/app/oms-events/node_modules/restify/lib/server.js:912:30)
  at f (/usr/app/oms-events/node_modules/once/once.js:25:25)
  at UserCache.findOne (/usr/app/oms-events/lib/middlewares.js:85:12)
message: 'Cast to ObjectId failed for value "hello" at path "_id"',
name: 'CastError',
kind: 'ObjectId',
value: 'hello',
path: '_id',
reason: undefined }

所以,问题是:如何通过 ObjectIDurl 字段找到元素?

我决定这样做:

let id = 'hello'

// Checking if the passed ID is ObjectID or not.
// I decided not to use ObjectID.isValid method, since it's not always
// working properly, see 
let findObject;
if (id.match(/^[0-9a-fA-F]{24}$/)) { // if it's indeed an ObjectID
  findObject = { _id: id };
} else {
  findObject = { url: id };
}

return Event
  .findOne(findObject)
  // doing something with the result