Поиск встроенных документов Mongoose + nodejs

Я новичок в Mongoose, и у меня возникла проблема с поиском.

Это мои схемы:

var CommentSchema = new Schema({
    body       : String
  , comments   : [CommentSchema]
});

var PostSchema = new Schema({
    body        : String
  , comments    : [CommentSchema]
});

Имеется глубокая вложенность комментариев. Когда кто-то отвечает на существующий комментарий, как мне его найти?


person kulebyashik    schedule 01.06.2011    source источник


Ответы (2)


вы можете посмотреть на набор тестов мангуста на github для примеров.

model_querying_test

Вот то, что вы ищете:

проверка нахождения на основе встроенных полей документа:

function () {
    var db = start(), BlogPostB = db.model('BlogPostB', collection);

    BlogPostB.create({comments: [{title: 'i should be queryable'}]}, function (err, created) {
      should.strictEqual(err, null);
      BlogPostB.findOne({'comments.title': 'i should be queryable'}, function (err, found) {
        should.strictEqual(err, null);
        found._id.should.eql(created._id);
        db.close();
      });
    });
    },
person Edward Chan    schedule 01.06.2011
comment
Но этот поиск только для одного уровня вложенности. Что, если у меня есть глубокая структура вложенности, и я хочу найти Blog { comments { comments { comments {this comment} }}}, и каждый раз, когда я хочу найти комментарий, я не знаю, сколько существует уровней вложенности. - person kulebyashik; 02.06.2011
comment
но подождите... у них одинаковая структура Comments.add({ comments : [Comments] }); дайте мне попробовать - person kulebyashik; 02.06.2011
comment
нет, не находит. Думаю, мне нужно искать его вручную. Дело в том, что я не знаю, как правильно. Если ручной поиск, вроде for(i=0...){if (hasComments) recursive()}, правильный, я так и сделаю. Я просто не знаю, есть ли более простой метод. p.s. в любом случае метод FindOne находит сообщение, а не комментарий. - person kulebyashik; 02.06.2011
comment
Метод findOne всегда будет возвращать документ верхнего уровня, в данном случае сообщение. Если вы хотите получить документы комментариев напрямую, вы должны поместить их в свой собственный документ верхнего уровня и связать их с помощью ObjectId, см. мой ответ ниже о том, как сделать это. - person Jed Watson; 16.10.2012

Одним из решений этого является хранение комментариев в виде отдельной модели, к которой вы можете напрямую обращаться, и сохранение ссылок на связанные идентификаторы объектов и пути между комментариями и сообщениями.

Использование функции Populate в документах, связанных с Mongoose, может функционировать аналогично встроенным документам, хотя есть некоторые важные отличия. в том, как вы их запрашиваете, и вы должны быть более осторожны, чтобы поддерживать заполненные отношения.

Настройте это так:

var mongoose = require('mongoose')
  , Schema = mongoose.Schema
  , ObjectId = Schema.Types.ObjectId;

var PostsSchema = new Schema({
  body     : String,
  stories  : [{ type: ObjectId, ref: 'Story' }]
});

var CommentsSchema = new Schema({
  body     : String,
  post     : { type: ObjectId, ref: 'Post' },
  comments : [{ type: ObjectId, ref: 'Comment' }]
});

var Story   = mongoose.model('Post', PostsSchema);
var Comment = mongoose.model('Comment', CommentsSchema);

Если вы сделаете это таким образом, потребуется больше запросов, чтобы получить сообщение со всеми его комментариями (что будет медленнее, чем возможность загрузить сообщение и его полную иерархию комментариев с помощью одного запроса), однако вы сможете запрашивать комментарии напрямую. и получить публикацию, в которой они были сделаны (но нелегко найти полный путь к комментарию, когда он вложен).

Все это компромиссы; лучшее решение (рекурсивно искать комментарии или сохранять их независимо, а затем рекурсивно загружать) должно быть принято в контексте вашего приложения и ожидаемых шаблонов его использования.

Еще одно предостережение; функция заполнения в настоящее время ограничена одним уровнем связанных ObjectId; вы должны вызывать его для каждого возвращаемого комментария, чтобы получить полный вложенный набор данных. Есть несколько подключаемых модулей, которые помогают в этом, например, mongoose-subpopulate. поддерживаться изначально в Mongoose — см. ошибку github здесь.

person Jed Watson    schedule 16.10.2012