在 MongoDB 中搜索一个包含在对象数组中的所有 ID 的集合

4

我有一个对象数组,只包含ObjectIDs,希望能够在集合中搜索所有这些ID对应的文档。

var array = [{ _id: 5551e59be360594cd3319644 },
             { _id: 5551e59be360594cd3319631 },
             { _id: 5551e59be360594cd33195d2 },
             { _id: 5551e59be360594cd3319627 }];

以下是我目前为了得到我的结果所做的事情:
for (var i = 0; i < array.length; i++) {
  db.collection('test').findOne({_id:array[i]._id}, function(err, matched) {
    console.log(matched);
});

我尝试使用$in运算符,但没有成功,因为它不是一个包含ID的数组,而是一个包含这些ID的对象数组。

有没有另一种方法只需进行一个数据库查询就可以完成,因为在for循环中执行太多的数据库查询不是一个好主意。

编辑 现在我尝试使用map方法(像@chrisdam解释的那样),所以我有了一个ID的数组,但当我将它传递给find方法时,我得到了这个结果:

编辑2 不要理会我的第一个编辑。 find()只返回一个光标,而不是文档本身。 所以我使用了toArray()。感谢@chrisdam的帮助!

{ db:
  { domain: null,
    _events: {},
    _maxListeners: undefined,
    databaseName: 'test',
    serverConfig: { 
      domain: null,
      _events: {},
      _maxListeners: undefined,
      auth: [Getter],
      _callBackStore: [Object],
      _commandsStore: [Object],
      _dbStore: [Object],
      host: 'localhost',
      port: 27017,
      options: [Object],
      internalMaster: true,
      connected: true,
      poolSize: 5,
      disableDriverBSONSizeCheck: false,
      _used: true,
      replicasetInstance: null,
      emitOpen: false,
      ssl: false,
      sslValidate: false,
      sslCA: null,
      sslCert: undefined,
      sslKey: undefined,
      sslPass: undefined,
      serverCapabilities: [Object],
      name: 'localhost:27017',
      socketOptions: [Object],
      logger: [Object],
      eventHandlers: [Object],
      _serverState: 'connected',
      _state: [Object],
      recordQueryStats: false,
      socketTimeoutMS: [Getter/Setter],
      _readPreference: [Object],
      db: [Circular],
      dbInstances: [Object],
      connectionPool: [Object],
      isMasterDoc: [Object] },
    options: { 
      read_preference_tags: null,
      read_preference: 'primary',
      url: 'mongodb://localhost:27017/test',
      native_parser: true,
      readPreference: [Object],
      safe: false,
      w: 1 },
    _applicationClosed: false,
    slaveOk: false,
    bufferMaxEntries: -1,
    native_parser: true,
    bsonLib: { 
      BSON: [Object],
      Long: [Object],
      ObjectID: [Object],
      DBRef: [Object],
      Code: [Object],
      Timestamp: [Object],
      Binary: [Object],
      Double: [Object],
      MaxKey: [Object],
      MinKey: [Object],
      Symbol: [Object] },
    bson: { promoteLongs: true },
    bson_deserializer: { 
      Code: [Object],
      Symbol: [Object],
      BSON: [Object],
      DBRef: [Object],
      Binary: [Object],
      ObjectID: [Object],
      Long: [Object],
      Timestamp: [Object],
      Double: [Object],
      MinKey: [Object],
      MaxKey: [Object],
      promoteLongs: true },
    bson_serializer: { 
      Code: [Object],
      Symbol: [Object],
      BSON: [Object],
      DBRef: [Object],
      Binary: [Object],
      ObjectID: [Object],
      Long: [Object],
      Timestamp: [Object],
      Double: [Object],
      MinKey: [Object],
      MaxKey: [Object],
      promoteLongs: true },
    _state: 'connected',
    pkFactory: { 
      [Function: ObjectID]
      index: 13651524,
      createPk: [Function: createPk],
      createFromTime: [Function: createFromTime],
      createFromHexString: [Function: createFromHexString],
      isValid: [Function: isValid],
      ObjectID: [Circular],
      ObjectId: [Circular] },
    forceServerObjectId: false,
    safe: false,
    notReplied: {},
    isInitializing: true,
    openCalled: true,
    commands: [],
    logger: { error: [Function], log: [Function], debug: [Function] },
    tag: 1431517732801,
    eventHandlers: { 
      error: [],
      parseError: [],
      poolReady: [],
      message: [],
      close: [] },
    serializeFunctions: false,
    raw: false,
    recordQueryStats: false,
    retryMiliSeconds: 1000,
    numberOfRetries: 60,
    readPreference: { _type: 'ReadPreference', mode: 'primary', tags: undefined } },
  collection: { 
    db: { 
      domain: null,
      _events: {},
      _maxListeners: undefined,
      databaseName: 'test',
      serverConfig: [Object],
      options: [Object],
      _applicationClosed: false,
      slaveOk: false,
      bufferMaxEntries: -1,
      native_parser: true,
      bsonLib: [Object],
      bson: [Object],
      bson_deserializer: [Object],
      bson_serializer: [Object],
      _state: 'connected',
      pkFactory: [Object],
      forceServerObjectId: false,
      safe: false,
      notReplied: {},
      isInitializing: true,
      openCalled: true,
      commands: [],
      logger: [Object],
      tag: 1431517732801,
      eventHandlers: [Object],
      serializeFunctions: false,
      raw: false,
      recordQueryStats: false,
      retryMiliSeconds: 1000,
      numberOfRetries: 60,
      readPreference: [Object] },
    collectionName: 'sick',
    internalHint: null,
    opts: {},
    slaveOk: false,
    serializeFunctions: false,
    raw: false,
    readPreference: { _type: 'ReadPreference', mode: 'primary', tags: undefined },
    pkFactory: { 
      [Function: ObjectID]
      index: 13651524,
      createPk: [Function: createPk],
      createFromTime: [Function: createFromTime],
      createFromHexString: [Function: createFromHexString],
      isValid: [Function: isValid],
      ObjectID: [Circular],
      ObjectId: [Circular] },
    serverCapabilities: undefined },
  selector: { _id: { '$in': [Object] } },
  fields: undefined,
  skipValue: 0,
  limitValue: 0,
  sortValue: undefined,
  hint: null,
  explainValue: undefined,
  snapshot: undefined,
  timeout: true,
  tailable: undefined,
  awaitdata: undefined,
  oplogReplay: undefined,
  numberOfRetries: 5,
  currentNumberOfRetries: 5,
  batchSizeValue: 0,
  raw: false,
  readPreference: { _type: 'ReadPreference', mode: 'primary', tags: undefined },
  returnKey: undefined,
  maxScan: undefined,
  min: undefined,
  max: undefined,
  showDiskLoc: undefined,
  comment: undefined,
  tailableRetryInterval: 100,
  exhaust: false,
  partial: false,
  slaveOk: false,
  maxTimeMSValue: undefined,
  connection: undefined,
  transforms: undefined,
  totalNumberOfRecords: 0,
  items: [],
  cursorId: { _bsontype: 'Long', low_: 0, high_: 0 },
  dbName: undefined,
  state: 0,
  queryRun: false,
  getMoreTimer: false,
  collectionName: 'test.sick' }

为什么不遍历列表并创建一个仅包含ID的新列表,然后将其与$in运算符一起使用。 - sirfz
@Sir_FZ 我们基本上是用 map 函数做到了这一点,不是吗? - anstaendig
1个回答

7
您可以尝试使用 JavaScript 的原生 map 方法生成一个 ObjectIds 数组,然后将其与 $in 运算符一起使用,如下所示:
var array = [{ _id: "5551e59be360594cd3319644" },
             { _id: "5551e59be360594cd3319631" },
             { _id: "5551e59be360594cd33195d2" },
             { _id: "5551e59be360594cd3319627" }],    
    ids = array.map(function (obj){ return ObjectId(obj._id)});

db.collection.find({ "_id": { "$in": ids }});

或者只需使用$or运算符,如下所示:

var array = [{ _id: "5551e59be360594cd3319644" },
             { _id: "5551e59be360594cd3319631" },
             { _id: "5551e59be360594cd33195d2" },
             { _id: "5551e59be360594cd3319627" }],    
    ids = array.map(function (obj){ return { _id: ObjectId(obj._id) } });   

db.collection.find({ "$or": ids });

有没有一种方法可以在单个查询中获取ID,然后获取这些ID对应的对象(可能需要某种形式的聚合)?谢谢 - theprogrammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接