Schema for User Ratings - Key/Value DB

前端 未结 4 973
暖寄归人
暖寄归人 2021-02-02 18:15

We\'re using MongoDB and I\'m figuring out a schema for storing Ratings.

  • Ratings will have values of 1-5.
  • I want to store other values such as from
4条回答
  •  孤独总比滥情好
    2021-02-02 18:40

    I would do it a bit different: Have a User class and a Rating class and aggregate the number of ratings and rating average.

    The Rating class

    This is a bit of pseudo code, but the meaning should be obvious.

    {
      _id:ObjectId(…),
      rating: Integer,
      rater: User._id
      rated: User._id
      date: ISODate()
    }
    

    In order to do the aggregation efficiently, you should at least create an index over rated:

    db.ratings.ensureIndex({rated:1})
    

    Now, you can decide between to approaches: either, you calculate the number of ratings and the average let's say once an hour and store it in an collection, let's say rate_averages, or you calculate those values on demand.

    Precalculated

    db.ratings.aggregate(
      // Aggregation
      [{
         $order: {
          _id: "$rated",
          ratings: { $sum:1 },
          average: { $avg: "$rating" }
        },
        {$out:'rate_averages'}
      ]
    )
    

    A document in the rate_averages collection will then look like this:

    {
      _id:User._id,
      ratings: Integer,
      average: Float
    }
    

    and is easily queryable for the individual user's values, as _id is indexed automatically.

    On demand

    You'd use the same rating and almost the same aggregation query, except that we add a $match stage so we only work with the values for the user we want to know the stats for and leave out the $out stage and have the document to be returned directly:

    db.ratings.aggregate([
      {
        $match:{ rated: <_id of the user we want the values for> },
      },
      {
        $order: {
          _id: "$rated",
          ratings: { $sum:1 },
          average: { $avg: "$rating" }
      }
    ])
    

    which would return a single document as shown for the user in question.

    With this approach and a proper data model, you can even do such things as "How many ratings were given by a specific user on a given date?" or "What are the most active raters/the most rated?" quite easily.

    Please read the aggregation framework docs for further details. You might find the data modeling docs useful, too.

提交回复
热议问题