MongoDB中电影票务系统的数据结构

时间:2017-07-23 06:56:18

标签: javascript mongodb mongoose mongoose-schema mongoose-populate

我正在尝试使用MongoDB制作影院预订系统。

我会在模型Movie中保留有关该电影的所有信息,包括titledescriptionactorsratingdirector等等。

但是,电影可以在不同房间和不同日期的电影院中播放,因此我还有一个模型Showtime,其中我有roomprice和{ {1}}。

最后,我还需要一个模型date,其中包含字段TicketpurchasedBypurchasedAt等。

但是,我不知道如何链接模型并提取放映时间。我想在首页上列出所有电影(包括标题,描述和图像),但我也想显示日期和价格。问题是日期和价格可能会有所不同,因为每部电影可能有多个(和不同的)日期和价格,所以我只想显示最小的价格和最快的日期。

目前,我的模式看起来像

isRedeemed

我可以通过在放映时间阵列中第一个showtime获得日期和价格

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [{ type: ObjectId, ref: 'Showtime' }]
});

但是,我需要按最近的日期和/或最低价格排序,所以我不确定我的数据结构是否适用于此目的。

什么是理想的,是能够做这样的事情:

Movie.find().populate('showtimes').then(movies => {
  movies.forEach(movie => {
    console.log(movie.showtimes[0].date)
    console.log(movie.showtimes[0].price)
  });
});

但由于我只在我的Movie.find().sort('showtimes.date showtimes.price').populate('showtimes').then(movies => { ... }); 字段中存储放映时间的ID,所以这是不可能的。

或者,我可以将架构更改为

showtimes

所以我不必使用showtimeSchema = Schema({ date: Date, price: Number }); movieSchema = Schema({ name: String, description: String, image: String, showtimes: [showtimeSchema] }); 。但问题是,当客户购买票证时,我需要在票证对象中引用showtime,因此我需要一个自己的放映时间模型。

修改

正如评论中所提到的,将文档直接嵌入populate()可能很聪明。但是,我不知道我的movieSchema模型应该是什么样的。

现在它就像是

Ticket

因此,当我打印机票时,我必须做类似

的事情
ticketSchema = Schema({
  showtime: { type: ObjectId, ref: 'Showtime' }
  purchasedAt: Date,
  purchasedBy: { type: ObjectId, ref: 'User' }
  isRedeemed: Boolean
})

1 个答案:

答案 0 :(得分:0)

我会使用你的第二个架构;因为您不会在showtime上进行交易,而是在访客,电影和门票上进行交易,因此在为放映时间创建新模型/集合时没有任何意义。所以看起来像这样:

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [{
    date: Date,
    price: Number
  }]
});

然后,你可以做的是sort by the min/max values of the array。所以这看起来像这样:

Movie.find().sort({'name.showtimes.date' : -1, price: 1})

这会拍摄每部电影的最新放映时间(以及最低价格)。

编辑:

你可以在故障单中引用电影,并在那里存储showtime:

ticketSchema = Schema({
  showtime: Date,
  purchasedAt: Date,
  purchasedBy: { type: ObjectId, ref: 'User' }
  isRedeemed: Boolean,
  movie: { type: ObjectId, ref: 'Movie' }
})

如果由于某种原因需要更多的结构,我会考虑使用SQL代替。嵌套填充(实际上是SQL JOIN)是维护/优化的噩梦,而RDBMS更适合这样的数据。

编辑2:

好的,让我们在这里权衡我们的选择。你是对的,如果时间/场地发生变化,你必须更新所有门票。因此,单独存储showtime给我们带来了好处。另一方面,这为您查找的虚拟每个票证增加了一层复杂性,更不用说性能损失和增加的服务器成本。即使票房/场地频繁发生变化,我也非常肯定您的票证查询频率更高。

话虽这么说,我认为这里的一个好方法是在showtime子项目上存储_id,并以这种方式查找你的门票:

showtimeSchema = Schema({
  date: Date,
  price: Number
});

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  // When you use a sub-schema like this, mongoose creates
  // an `_id` for your objects.
  showtimes: [showtimeSchema]
});

// Now you can search movies by showtime `_id`.
Movie.find({showtimes: 'some showtime id'}).exec()

您可以更进一步,在Movie模型上注册static,以便通过showtime _id轻松查找:

Movie.findByShowtime('some showtime id').exec()

当你拍摄电影时,你可以像这样抓住showtime:

var st = movie.showtimes.id('some showtime id');

Further reading on subdocuments.