Database Reference
In-Depth Information
A VERAGE PRODUCT RATINGS
Products are amenable to numerous update strategies. Assuming that administrators
are provided with an interface for editing product information, the easiest update
involves fetching the current product document, merging that data with the user's
edits, and issuing a document replacement. At other times, you may need to update
just a couple of values, where a targeted update is clearly the way to go. This is the case
with average product ratings. Because users need to sort product listings based on
average product rating, you store that rating in the product document itself and
update the value whenever a review is added or removed.
Here's one way of issuing this update:
average = 0.0
count = 0
total = 0
cursor = @reviews.find({:product_id => product_id}, :fields => ["rating"])
while cursor.has_next? && review = cursor.next()
total += review['rating']
count += 1
end
average = total / count
@products.update({:_id => BSON::ObjectId("4c4b1476238d3b4dd5003981")},
{'$set' => {:total_reviews => count, :average_review => average}})
This code aggregates and produces the rating field from each product review and
then produces an average. You also use the fact that you're iterating over each rating
to count the total ratings for the product. This saves an extra database call to the
count function. With the total number of reviews and their average rating, the code
issues a targeted update, using $set .
Performance-conscious users may balk at the idea of reaggregating all product
reviews for each update. The method provided here, though conservative, will likely
be acceptable for most situations. But other strategies are possible. For instance, you
could store an extra field on the product document that caches the review ratings
total. After inserting a new review, you'd first query for the product to get the current
total number of reviews and the ratings total. Then you'd calculate the average and
issue an update using a selector like the following:
{'$set' => {:average_review => average, :ratings_total => total},
'$inc' => {:total_reviews => 1}})
Only by benchmarking against a system with representative data can you say whether
this approach is worthwhile. But the example shows that MongoDB frequently pro-
vides more than one valid path. The requirements of the application will help you
decide which is best.
T HE CATEGORY HIERARCHY
With many databases, there's no easy way to represent a category hierarchy. This is true
of MongoDB, although the document structure does help the situation somewhat.
Documents permit a strategy that optimizes for reads, since each category can contain
Search WWH ::




Custom Search