2015-10-31 2 views
4

У меня есть эта Mongoose схема:Mongoose - получить длину массива в модели

var postSchema = mongoose.Schema({ 

    postId: { 
     type: Number, 
     unique: true 
    }, 

    upvotes: [ 
     { 
      type: Number, 
      unique: true 
     } 
    ] 

}); 

что лучший запрос, чтобы использовать, чтобы получить длину массива upvotes? Я не считаю, что мне нужно использовать агрегацию, потому что я хочу только запросить одну модель, просто нужна длина массива upvotes для данной модели.

Действительно изо всех сил пытается найти эту информацию в Интернете - все, что я ищу, упоминает методологию агрегирования, которую я не считаю нужным.

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

+0

Почему вы не хотите использовать агрегацию? –

+0

[Почему, по вашему мнению, вам не нужна агрегация?] (Http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – styvane

+0

Для уникальной части индекса вашего вопроса, см. http://stackoverflow.com/questions/15921700/mongoose-unique-values-in-nested-array-of-objects – JohnnyHK

ответ

5

find результаты могут включать в себя только контент из Документов сами , в то время как aggregate может проецировать новые значения, которые являются производными от doc (например, длина массива). Вот почему вам нужно использовать aggregate, хотя вы получаете только один документ.

Post.aggregate([{$match: {postId: 5}}, {$project: {upvotes: {$size: '$upvotes'}}}]) 

Одно исключение является оператором $meta проекции проекта оценка результата $text запроса.

+1

Я попробую это, но я клянусь, что пробовал эту последнюю ночь, и она не работала –

+2

, похоже, работает , спасибо –

+0

Но '' '' Aggregation''' возвращает объекты JSON вместо объектов '' '' Model''''. Поэтому мы не можем выполнять какую-либо операцию в возвращенных документах. Любые другие способы? –

1

Мое предложение было бы вытащить весь upvotes поля данных и использовать .Length свойство возвращенного массива в Node.js код

//logic only, not a functional code 
post.find(filterexpression, {upvote: 1}, function(err, res){ 
    console.log(res.upvotes.length); 
}); 

EDIT:

Другой способ сделать будет сохранен Javascript. Вы можете запросить upvote и посчитайте то же самое в стороне MongoDB хранящегося Javascript с использованием .Length

+0

Я думаю, что в идеале мы хотели бы сделать mongo делать работу и оставить столько же кода из Узел.js, возможно, это возможно, но это может сработать –

+0

См. мое редактирование для альтернативы – prasun

+0

спасибо - решение JohnnyHKs на сегодняшний день является самым лучшим из –

5

Я обычно не поклонник кеширования значений, но это может быть вариант (и после обнаружения этого ответа stackoverflow то, что я собираюсь сделать для моего использования), чтобы вычислить длину поля, когда запись обновляется в pre ('validate') hook. Например:

var schema = new mongoose.Schema({ 
    name: String, 
    upvoteCount: Number, 
    upvotes: [{}] 
}); 

schema.pre('validate', function (next) { 
    this.upvoteCount = this.upvotes.length 
    next(); 
}); 

Сразу отметим, что вам нужно сделать ваши обновления мангуст путь по загрузке объекта с помощью функции поиска, а затем сохранить изменения с помощью object.save() - не использовать findOneAndUpdate