2011-06-01 7 views
0

Im new to Mongoose, и я столкнулся с проблемой при поиске.Поиск вложенных документов Mongoose + nodejs

Это мои Schemas:

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

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

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

ответ

0

Вы можете посмотреть пример набора тестов mongoose на 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(); 
     }); 
    }); 
    }, 
+0

Но этот поиск предназначен только для одного уровня гнездования. Что делать, если у меня есть глубокая структура вложенности и я хочу найти 'Блог { комментариев { комментариев { комментариев {этого комментария} }}}' и каждый раз, когда я хочу, чтобы найти комментарии я не» Знать, сколько уровней гнездования существует. – kulebyashik

+0

, но подождите ... у них такая же структура 'Comments.add ({ комментариев: [Комментарии] });' Позвольте мне попробовать – kulebyashik

+0

nope, он не находит его. Думаю, мне нужно его искать вручную. Дело в том, что я не знаю «правильного пути». Если поиск вручную, smth, как 'for (i = 0 ...) {if (hasComments) recursive()}', является «правильным», поэтому я сделаю это. Я просто не знаю, есть ли более простой метод. стр. В любом случае метод FindOne находит сообщение, а не комментарий. – kulebyashik

0

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

Использование функции 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); 

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

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

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

Смежные вопросы