【问题标题】:Data structure for movie ticketing system in MongoDBMongoDB中电影票务系统的数据结构
【发布时间】:2017-07-25 02:59:39
【问题描述】:

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

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

但是,一部电影可以在不同的房间和不同的日期在电影院放映,所以我还有一个模型Showtime,我有roompricedate

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

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

目前,我有一个看起来像这样的架构

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]
});

所以我不必使用populate()。但是,问题是当客户购买门票时,我需要在门票对象中引用放映时间,因此我需要自己的放映时间模型。

编辑

正如 cmets 中提到的,将文档直接嵌入到 movieSchema 中可能很聪明。但是,我不知道我的Ticket 模型应该是什么样子。

现在是这样的

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

所以当我打印票时,我必须做类似的事情

Ticket.findById(ticketId).populate({
  path: 'Showtime',
  populate: {
    path: 'Movie'
  }
}).then(ticket => {
  console.log(ticket.date);
  console.log(ticket.event.name);
});

【问题讨论】:

  • 如果您确实需要以这种方式查询,那么嵌入是您的最佳选择。 .populate() 所做的只是向 MongoDB 发出另一个查询,以便从另一个集合中获取其他信息。在现代 MongoDB 版本中,它实际上基本上被 $lookup 取代,因为它实际上只是为了“模拟”连接而创建的,而 $lookup“实际上是”连接。但尽管如此,“加入”在性能方面是错误的,因此您实际上应该将“相关”数据保留在同一个文档中。
  • 之所以是“评论”,是因为您的问题接近征求意见或通常过于宽泛。所以实际上以现在直接征求意见的方式编辑它,或者基本上“扩大主题”对你没有任何好处。也许您实际上有A New Question 或确实有几个,以便找出您需要理解的与一个或另一个用例相关的概念。这样,您可能会比从“一个大问题”中获得更多信息。

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


【解决方案1】:

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

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})

这会获取每部电影的最新放映时间并按该时间排序(以及最低价格)。

编辑:

您可以在门票中引用电影,并将放映时间也存储在那里:

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

如果您出于某种原因需要更多的结构,我会考虑使用 SQL。嵌套填充(本质上是 SQL JOIN)是维护/优化的噩梦,而 RDBMS 更适合此类数据。

编辑 2:

好的,让我们在这里权衡一下我们的选择。没错,如果时间/地点发生变化,您将不得不更新所有门票。因此,单独存储放映时间会给我们带来好处。另一方面,这现在为您查找的几乎每一个票证增加了一层复杂性,更不用说性能损失和增加的服务器成本了。即使门票/场地经常发生变化,我几乎可以肯定您的门票查找更加频繁。

话虽如此,我认为这里的一个好方法是在放映时间主题上存储_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()

获取电影后,您可以像这样抓住放映时间:

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

Further reading on subdocuments.

【讨论】:

  • 谢谢,但我不知道如何安排我的门票。我已经更新了我的问题
  • 已编辑。让我知道这是否有帮助。
  • 但是,例如,如果我必须更改放映时间的地点或日期,它不会影响所有门票。我可以直接在票中引用存储在电影放映时间数组中的放映时间对象吗?
  • 我想我了解您的问题。已编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-13
  • 2023-04-06
  • 2017-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
相关资源
最近更新 更多