我对设计mongo数据库(或基于集合的数据库)感到困惑

时间:2014-07-22 08:15:44

标签: node.js mongodb mongoose nosql

在设计SQL数据库时,有一些明确的规则(规范化规则)。

所以,鉴于这个模型:

  • 有地方
  • 有活动
  • 地点有姓名,纬度,经度
  • 事件有name,startDate,endDate
  • 每个活动都在一个地方举办(所以一个地方有很多活动)

在SQL中以这种方式设计它很容易,有两个表:

Places(placeId, name, lat, lng)
Events(eventId, placeId, name, startDate, endDate)

这是不正确的,这是正确的。没有多少选择......

通过这种设计,我有一些好处:

  • 如果我更新地名,我不必关心事件..联接完成工作
  • 我可以忘记地点和处理事件(例如:显示按开始日期排序的事件)
  • 我可以忘记事件并使用地点(按照与某些用户的距离排序显示事件等)

现在,我正在尝试在MongoDb中设计相同的模型,我不确定它,因为有很多替代方法可以实现这一目标:

  • 两个集合:不包含事件的地方,以及不包含地点的事件(但保留placeId字段)

    var placeSchema = new mongoose.Schema({
        name: String,
        lat: Number,
        lng: Number,
    });
    
    var eventSchema = new mongoose.Schema({
        name: String,
        startDate: Date,
        endDate: Date,
        placeId: mongoose.Schema.Types.ObjectId,
    });
    
  • 两个集合:包含事件的地方和不包含地点的事件(但保留placeId字段)

    var placeSchema = new mongoose.Schema({
        name: String,
        lat: Number,
        lng: Number,
        events: [eventSchema]
    });
    
    var eventSchema = ...
    
  • 两个集合:包含事件和包含地点的事件的地方(不同文档中的重复数据)

  • 包含活动的一个地方集合

    var placeSchema = new mongoose.Schema({
        name: String,
        lat: Number,
        lng: Number,
        events: [eventSchema]
    });
    

在上述所有选择中,我可以想象出麻烦。如果我需要更新名称(作为地名或事件名称),我需要在多个文档中更新它。例如,在“一个地方集合”方法中,一个事件不包含一个地方..所以如果我将一个事件对象单独传递给我的视图,那么该视图将不会知道包含该事件的地方! / p>

所以,我的问题是两个:

  1. 此型号的优秀设计是什么?

  2. 我为了这篇文章简化了模型..但实际上事件有标签,事件和地方都有图片。我可以在这里描述整个模型,但这将是滥用。 我想知道设计mongoDB数据库(基于文档的数据库)的规则。规范化规则清楚地说明了如何应用它们以及它们的好处(主要是维护,例如更新时的干净代码等)。 这里有明确的规则吗?。此外,这些(规范化)规则非常直观,通过跳过文献,无论如何都可以采用正确的方式。

1 个答案:

答案 0 :(得分:1)

嗯,这实际上取决于您对架构的要求。

首先要做的事情:您为"两个集合编写的代码:包含事件的地方,以及不包含地点的事件(但保留placeId字段)"应该这样:

var placeSchema = new mongoose.Schema({
    name: String,
    lat: Number,
    lng: Number,
    events: [mongoose.Schema.Types.ObjectId]
});

var eventSchema = ...

因为mongodb没有加入,所以通常你必须进行非规范化,直到你有充分的理由进行规范化。

在您想要做的事情中,如果您的地方可能有很多活动,那么以分页模式或类似的方式获取事件会让您的查询变小。在那种情况下,我更喜欢"两个集合:包含事件的地方,以及不包含地点的事件"。 但是如果你的地方最多只有几个活动,我会将它们全部保存在一个系列中。 此外,如果您想直接访问事件,最好将它们分成两个集合,如果需要,可以在事件集合中放置地名和_id(不要太担心重复,大多数情况下都是如此) ,速度和小查询是你必须关心的。)

对于更新,mongodb提供了更新的好工具。例如,如果您很少进行更改(例如更改地名),请不要将其标准化。

还有一件事,mongoose提供了很好的工具,例如population