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

Javascript MongoDB电影票务系统的数据结构,javascript,mongodb,mongoose,mongoose-schema,mongoose-populate,Javascript,Mongodb,Mongoose,Mongoose Schema,Mongoose Populate,我正在尝试使用MongoDB为电影院制作预订系统 我将有关电影的所有信息保存在一个模型中,包括标题,描述,演员,评级,导演,等等 然而,电影可以在不同的房间和不同的日期在电影院放映,因此我也有一个模型Showtime,其中我有room、price、和date 最后,我还需要一张带有字段purchasedBy、purchasedAt、isredemed的模型Ticket 但是,我不知道如何链接模型和提取展示时间。我想在frontpage上列出所有电影(包括标题、描述和图片),但我也想显示日期和价格

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

我将有关电影的所有信息保存在一个模型中,包括
标题
描述
演员
评级
导演
,等等

然而,电影可以在不同的房间和不同的日期在电影院放映,因此我也有一个模型
Showtime
,其中我有
room
price
、和
date

最后,我还需要一张带有字段
purchasedBy
purchasedAt
isredemed
的模型
Ticket

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

目前,我有一个类似于

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [{ type: ObjectId, ref: 'Showtime' }]
});
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);
});
我可以通过在一系列的showtime中选择第一个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 => {
  ...
});
Movie.find().sort({'name.showtimes.date' : -1, price: 1})
var st = movie.showtimes.id('some showtime id');
但是,由于我只在我的
showtimes
字段中存储showtimes的ID,这是不可能的

或者,我可以将模式更改为

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

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [showtimeSchema]
});
因此,我不必使用
populate()
。但是,问题是,当客户购买一张票时,我需要在ticket对象中引用showtime,因此我需要一个showtime模型

编辑 如评论中所述,将文档直接嵌入到
movieSchema
中可能是明智之举。但是,我不知道我的
车票
型号应该是什么样子

现在有点像

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [{ type: ObjectId, ref: 'Showtime' }]
});
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);
});
所以当我在打印票的时候,我必须做一些类似的事情

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [{ type: ObjectId, ref: 'Showtime' }]
});
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);
});

我会使用你的第二个模式;为showtimes创建新的模型/集合是毫无意义的,因为您不会在showtimes上进行交易,而是在访客、电影和门票上进行交易。看起来是这样的:

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [{
    date: Date,
    price: Number
  }]
});
那么,你能做的就是。所以看起来是这样的:

Movie.find().sort('showtimes.date showtimes.price').populate('showtimes').then(movies => {
  ...
});
Movie.find().sort({'name.showtimes.date' : -1, price: 1})
var st = movie.showtimes.id('some showtime id');
这将获取每部电影的最新放映时间,并按该时间进行排序(以及最低价格)

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

ticketSchema = Schema({
  showtime: Date,
  purchasedAt: Date,
  purchasedBy: { type: ObjectId, ref: 'User' }
  isRedeemed: Boolean,
  movie: { type: ObjectId, ref: 'Movie' }
})
如果出于任何原因需要更多的结构,我会考虑使用SQL。嵌套填充(本质上是SQL连接)是维护/优化的噩梦,RDBMS更适合这样的数据

编辑2: 好的,让我们在这里权衡一下我们的选择。你说得对,如果时间/地点发生变化,你必须更新所有门票。因此,单独存储showtime为我们带来了这一好处。另一方面,这实际上给您查找的每一张票证都增加了一层复杂性,更不用说性能损失和增加的服务器成本了。即使门票/场地频繁变动,我几乎可以肯定的是,您的门票查询会更加频繁

话虽如此,我认为这里的一个好方法是在showtime子对象上存储
\u 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()
您可以在这里更进一步,在
电影
模型上注册,以便通过showtime
\u id
轻松查找:

Movie.findByShowtime('some showtime id').exec()
拍摄完电影后,您可以像这样把握放映时间:

Movie.find().sort('showtimes.date showtimes.price').populate('showtimes').then(movies => {
  ...
});
Movie.find().sort({'name.showtimes.date' : -1, price: 1})
var st = movie.showtimes.id('some showtime id');

我会使用你的第二个模式;为showtimes创建新的模型/集合是毫无意义的,因为您不会在showtimes上进行交易,而是在访客、电影和门票上进行交易。看起来是这样的:

movieSchema = Schema({
  name: String,
  description: String,
  image: String,
  showtimes: [{
    date: Date,
    price: Number
  }]
});
那么,你能做的就是。所以看起来是这样的:

Movie.find().sort('showtimes.date showtimes.price').populate('showtimes').then(movies => {
  ...
});
Movie.find().sort({'name.showtimes.date' : -1, price: 1})
var st = movie.showtimes.id('some showtime id');
这将获取每部电影的最新放映时间,并按该时间进行排序(以及最低价格)

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

ticketSchema = Schema({
  showtime: Date,
  purchasedAt: Date,
  purchasedBy: { type: ObjectId, ref: 'User' }
  isRedeemed: Boolean,
  movie: { type: ObjectId, ref: 'Movie' }
})
如果出于任何原因需要更多的结构,我会考虑使用SQL。嵌套填充(本质上是SQL连接)是维护/优化的噩梦,RDBMS更适合这样的数据

编辑2: 好的,让我们在这里权衡一下我们的选择。你说得对,如果时间/地点发生变化,你必须更新所有门票。因此,单独存储showtime为我们带来了这一好处。另一方面,这实际上给您查找的每一张票证都增加了一层复杂性,更不用说性能损失和增加的服务器成本了。即使门票/场地频繁变动,我几乎可以肯定的是,您的门票查询会更加频繁

话虽如此,我认为这里的一个好方法是在showtime子对象上存储
\u 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()
您可以在这里更进一步,在
电影
模型上注册,以便通过showtime
\u id
轻松查找:

Movie.findByShowtime('some showtime id').exec()
拍摄完电影后,您可以像这样把握放映时间:

Movie.find().sort('showtimes.date showtimes.price').populate('showtimes').then(movies => {
  ...
});
Movie.find().sort({'name.showtimes.date' : -1, price: 1})
var st = movie.showtimes.id('some showtime id');

如果您真的需要用这种方式进行查询,那么嵌入就是一种方式。
.populate()
所做的就是向MongoDB发出另一个查询,以便从另一个集合获取其他信息。在现代MongoDB版本中,它基本上被
$lookup
取代,因为它实际上只是为了“模拟”一个连接而创建的,而
$lookup
实际上是“执行”连接。但是,从性能角度来看,“加入”是错误的,因此您实际上应该将“相关”数据保存在同一文档中。之所以将其作为“评论”,是因为您的问题接近于征求意见或建议