MongoDB, Mongoose: как найти вложенный документ в найденном документе?

Я застрял, пытаясь сделать его как _id в найденном документе.

Пример Схемы

var User = mongoose.Schema({
        name:       String,
        photos:    [{src: String, title: String}]
    });
var Team = db.model('Team', Team);

теперь я получаю одного пользователя:

myUser = User.findOne(...)...

как я могу получить теперь src его фото это _id (или title)?

что-то типа:

myUser.photos.findOne({'_id': myId})

2 ответов


вам нужно либо создать новую схему для встроенных документов, либо оставить объявление типа в виде пустого массива so mongoose интерпретируется как Mixed тип.

var userSchema = new mongoose.Schema({
  name: String,
  photos: []
});
var User = mongoose.model('User', userSchema);

-- или --

var userSchema = new mongoose.Schema({
  name: String,
  photos: [photoSchema]
});

var photoSchema = new mongoose.Schema({
  src: String,
  title: String
});

var User = mongoose.model('User', userSchema);

и тогда вы можете сохранить таким образом:

var user = new User({
  name: 'Bob',
  photos: [ { src: '/path/to/photo.png' }, { src: '/path/to/other/photo.png' } ]
});

user.save();

отсюда вы можете просто использовать примитивы массива, чтобы найти встроенные документы:

User.findOne({name: 'Bob'}, function (err, user) {

  var photo = user.photos.filter(function (photo) {
    return photo.title === 'My awesome photo';
  }).pop();

  console.log(photo); //logs { src: '/path/to/photo.png', title: 'My awesome photo' }
});

-- или --

вы можете использовать специальный id() метод во встроенных документах для поиска по id:

User.findOne({name: 'Bob'}, function (err, user) {
    user.photos.id(photo._id);
});

вы можете прочитать больше здесь:http://mongoosejs.com/docs/subdocs.html

убедитесь, что вы НЕ зарегистрируйте схему с Мангустом, иначе она создаст новую коллекцию. Также имейте в виду, что если часто искать дочерние документы, было бы неплохо использовать refs и population как показано ниже. Несмотря на то, что он дважды попадает в БД, его гораздо быстрее из-за индексации. Кроме того,mongoose будет Бонк на двойной вложенности docs (т. е. у детей также есть дочерние документы)

var user = mongoose.Schema({
  name: String,
  photos: [{ type: Schema.Types.ObjectId, ref: 'Photo' }]
});

var photo = mongoose.Schema({
  src: String,
  title: String
});

User
  .findOne({ name: 'foo' })
  .populate('photos')
  .exec(function (err, user) {
    console.log(user.photos[0].src);
  });

соответствующие документы можно найти здесь http://mongoosejs.com/docs/populate.html


добавив к ответу srquinn, из моего ограниченного опыта я подумал populate для вступления документов из разных коллекций?

Я думаю, здесь вы могли бы просто сделать User.findOne({ name: 'foo' }, 'photos'), который является сокращением для:

const query = User.findOne({ name: 'foo' })
query.select('photos')