2010-08-05 5 views
3

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

Я использую рельсы с mongodb, НО Я не думаю, что мне нужно получить появление категорий из db, поэтому часть mongo не имеет значения.

Это то, что я до сих пор

 
@recent_posts = current_user.recent_posts #returns the 10 most recent posts 
@categories_hash = {'tech' => 0, 'world' => 0, 'entertainment' => 0, 'sports' => 0} 
    @recent_posts do |cat| 
     cat.categories.each do |addCat| 
     @categories_hash.increment(addCat) #obviously this is where I'm having problems 
     end 
    end 
end 

структура пост является

{"_id" : ObjectId("idnumber"), "created_at" : "Tue Aug 03...", "categories" :["world", "sports"], "message" : "the text of the post", "poster_id" : ObjectId("idOfUserPoster"), "voters" : []}

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

ответ

1

Если вы используете mongodb, элегантным способом агрегирования использования тегов является использование операции map/reduce. Mongodb поддерживает операции с картой/сокращением с использованием кода JavaScript. Маршрутизация карт/сокращений на сервере (-ах) db, то есть вашему приложению не нужно извлекать и анализировать каждый документ (который не будет хорошо масштабироваться для больших коллекций).

В качестве примера приведена карта и функции сокращения, которые я использую в своем блоге в коллекции статей для объединения использования тегов (которые используются для создания облака тегов на боковой панели). Документы в коллекции статей есть ключ с именем «тегами», который хранит массив строк (значения тегов)

Функция карты просто излучает 1 на каждый используемого тега для подсчета его:

function() { 
    if (this.tags) { 
    this.tags.forEach(function (tag) { 
     emit(tag, 1); 
    }); 
    } 
} 

Уменьшить функцию суммирует отсчеты:

function (key, values) { 
    var total = 0; 
    values.forEach(function (v) { 
    total += v; 
    }); 
    return total; 
} 

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

{ 'rails' => 5, 'ruby' => 12, 'linux' => 3 } 
+0

Ну, у меня возникло соблазн учиться и использовать карту/уменьшить в любом случае, я думал, что это был более простой способ сделать это с рубином, но я дам вам шанс и отчитаться. – pedalpete

+0

Это, безусловно, легче сделать в Ruby, но и менее эффективно, хотя этого все равно может быть достаточно для небольших сайтов. Я опубликовал другой ответ с изменением исходного кода. – Zargony

7

Если вы не знакомы с картой/уменьшить, и вы не заботитесь о расширении, это не так элегантно, как карта/уменьшить, но должно быть достаточно для небольших сайтов:

@categories_hash = Hash.new(0) 
current_user.recent_posts.each do |post| 
    post.categories.each do |category| 
    @categories_hash[category] += 1 
    end 
end 
+3

Вы также можете удалить '@categories_hash [category] || = 0', если вы изменили первую строку на' @categories_hash = Hash.new (0) 'или инициализировали ее, как в исходном вопросе. –

+0

Вы правы, спасибо. Я всегда забываю о значениях по умолчанию хэш. Редактирование ... – Zargony

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