Golang中的嵌套对象在MongoDB中的处理方式

huangapple go评论73阅读模式
英文:

Golang nested objects in MongoDB

问题

我目前正在开发一个小应用程序,允许用户对特定对象进行评分,我的数据库(MongoDB)结构如下:

电影 {
    Id int
    名称 string
}
演员 {
    Id int
    名称 string
    年龄 int
}
电影_演员 {
    电影 电影
    演员 演员
}
用户 {
    Id int
    用户名 string
    密码 string
}
评分 {
    Id int
    用户 用户
    演员 演员
    评分 int
}

当我想要选择在某个电影中评分少于5个的所有“演员”时,我的问题就开始了:

// db *mgo.Database
c := db.C('ratings')
err := c.Find(...)
英文:

I'm currently working on a small application that allows users to rate certain objects, my database (MongoDB) structure looks like this

Movie {
	Id int
	Name string
}
Actor {
	Id int
	Name string
	Age int
}
Movie_Actors {
	Movie Movie
	Actor Actor
}
User {
	Id int
	Username string
	Password string
}
Rating {
	Id int
	User User
	Actor Actor
	Rating int
}

My problem begins when I want to select all Actors in a Movie where there are less than 5 Ratings

// db *mgo.Database
c := db.C('ratings')
err := c.Find(...)

答案1

得分: 1

对于这个问题,我会稍微调整你的模式,以使在MongoDB中进行查询更加自然。仅查看你在此查询中所需的类型,你可以使用以下代码:

type Movie struct {
    Id     bson.ObjectId `bson:"_id,omitempty"`
    Name   string
    Actors []bson.ObjectId
}

type Actor struct {
    Id       bson.ObjectId `bson:"_id,omitempty"`
    Name     string
    Age      int
    Ratings  []Rating
    NRatings int
}

在这个设计中,电影直接嵌入了演员的ID,而演员则通过一个单独的字段来跟踪评分的数量,而不是将评分本身嵌入其中。如果你只想运行这种类型的查询,你可以通过将电影直接嵌入到演员中来完全去规范化数据模型。这将进一步简化查询,但也会导致大量的信息重复,并阻止你将电影视为单独的实体。

在这个设计中,你可以使用以下代码找到电影《Fantastic Mr. Fox》中评分少于5的演员:

// 查找电影中的演员
var m Movie
db.C("movies").Find(bson.M{"name": "Fantastic Mr. Fox"}).One(&m)

// 过滤演员,找到评分少于5的演员
var results []Actor
db.C("actors").Find(bson.M{"_id": bson.M{"$in": m.Actors}, "nratings": bson.M{"$lt": 5}}).All(&results)
fmt.Println(results)

你可以参考模式设计文档来了解这些权衡的讨论。

英文:

For this problem, I would denormalize your schema a little to make querying in MongoDB more natural. Looking only at the types you need for this query, you might use the following:

type Movie struct {
    Id     bson.ObjectId `_id,omitempty`
    Name   string
    Actors []bson.ObjectId
}

type Actor struct {
    Id     bson.ObjectId `_id,omitempty`
    Name     string
    Age      int
    Ratings []Rating
    NRatings int
}

Here the Movie directly embeds the Actor IDs, and the Actor keeps track of the number of ratings in a separate field from the ratings themselves. If you only wanted to run this single type of query, you could fully denormalize the data model by embedding the Movies directly into the Actors who played in them. This would simplify the query even more, but would also create a lot of duplication of information and prevent you from dealing with Movies as separate entities.

See the documentation on schema design for a discussion on these tradeoffs.

In this design, you can find the actors in the movie Fantastic Mr. Fox with fewer than 5 ratings using the following:

// Find the actors in the movie
var m Movie
db.C("movies").Find(bson.M{"name": "Fantastic Mr. Fox"}).One(&m)

// Filter the actors to find those with less than 5 ratings.
var results []Actor
db.C("actors").Find(bson.M{"_id": bson.M{"$in": m.Actors}, "nratings": bson.M{"$lt": 5}}).All(&results)
fmt.Println(results)

huangapple
  • 本文由 发表于 2015年1月31日 18:39:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/28250668.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定