Designing a Datastore schema for a page that users can edit (e.g. a wikipedia/stackoverflow page)

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

Designing a Datastore schema for a page that users can edit (e.g. a wikipedia/stackoverflow page)

问题

设计一个包含基本信息和Markdown内容字段的表/实体,允许用户轻松创建表格等。

我想的是这样的:

type Tournament struct {
  ID int64 `datastore:"-"`
  MDContent []byte `datastore:",noindex"`
  Name string
  URL string
  DateCreated int64
  CreatedBy string
  DateUpdated int64
  UpdatedBy string
  ApprovalStatus int64 // 0=待决定, 1=已批准, 2=已拒绝, 3=已停用
  ApprovalBy string
}

我的问题是如何更新它。ID字段也将用作URL路径,例如,如果一个实体的ID为7,则它将显示在example.com/tournament/7。

我认为这就排除了简单地创建一个具有更新数据的新实体,然后在上一个实体上设置ApprovalStatus=3的可能性,因为如果这样做,example.com/tournament/7 URL将不再请求正确的ID。

我也不喜欢创建自己的唯一ID的想法,因为我认为利用Datastore ID生成会更好(这也使得根据URL轻松获取正确的实体);我考虑创建一个新的实体/表来跟踪修订,但我不确定所有这些是否高效,所以我希望一些专家能给予一些建议。


与@mkopriva解决方案相关的更新:

如果按照这种方式进行,我认为在TournamentEdit实体结构中需要包含一个TournamentID字段。

type TournamentEdit struct {
    ID             int64   `datastore:"-"`
    TournamentID   int64
    MDContent      []byte `datastore:",noindex"`
    DateCreated    int64
    CreatedBy      string
    ApprovalStatus int64 // 0=待决定, 1=已批准, 2=已拒绝, 3=已停用
    ApprovalBy     string
}

然后,检索函数可能如下所示:

func (db *datastoreDB) GetTournamentByKeyID(ctx context.Context, keyID int64) (*Tournament, error) {
  key := datastore.IDKey("Tournament", keyID, nil)
  var tournament Tournament
  err := db.client.Get(ctx, key, &tournament)
  // 错误检查
  tournament.ID = key.ID
  
  var edits []TournamentEdit
  query := datastore.NewQuery("TournamentEdit")
  query = query.Filter("TournamentID =", tournament.ID)
  query = query.Filter("ApprovalStatus =", 1)
  if _, err := db.client.GetAll(ctx, query, &edits); err != nil {
    // 错误检查
  }
  tournament.Edits = edits // 我猜这样做是错误的方式?
  return &tournament, nil
}

这样可以吗?

英文:

The idea is to design a table/entity that contains some basic info, as well as a Markdown-Content field that would allow users to easily create tables and such.

I'm thinking something like this:

type Tournament struct {
  ID in64 `datastore:"-"`
  MDContent []byte `datastore:",noindex"`
  Name string
  URL string
  DateCreated int64
  CreatedBy string
  DateUpdated int64
  UpdatedBy string
  ApprovalStatus int64 // 0=to be decided, 1=approved, 2=rejected, 3=discontinued
  ApprovalBy string
}

My problem is figuring out how to update it. The ID field will also be used as the URL path, e.g. if an entity has ID 7 then it will be displayed on example.com/tournament/7.

I believe this eliminates the possibility of simply creating a new entity with updated data, and then set the ApprovalStatus=3 on the previous entity, because if you do as such then the example.com/tournament/7 URL will no longer request the correct ID.

I also don't like the idea of creating my own unique ID because I think it would be great to simply take advantage of the Datastore ID generation (which also makes it easy to get the correct entity based on URL); I considered creating a new entity/table that would keep track of revisions but I'm not sure how efficient all of this is, so I was hoping some expert might be able to give some advice.


Update related to @mkopriva solution:

If you do it this way, then it's necessary to include a TournamentID field inside the TournamentEdit entity struct I think?

type TournamentEdit struct {
    ID             in64   `datastore:"-"`
    TournamentID   int64
    MDContent      []byte `datastore:",noindex"`
    DateCreated    int64
    CreatedBy      string
    ApprovalStatus int64 // 0=to be decided, 1=approved, 2=rejected, 3=discontinued
    ApprovalBy     string
}

And then the retrieve function could look like this:

func (db *datastoreDB) GetTournamentByKeyID(ctx context.Context, keyID int64) (*Tournament, error) {
  key := datastore.IDKey("Tournament", keyID, nil)
  var tournamnet Tournament
  err := db.client.Get(ctx, key, &tournament)
  // err checking
  tournament.ID = key.ID
  
  var edits TournamentEdits
  query := datastore.NewQuery("TournamentEdit")
  query = query.Filter("TournamentID =", tournament.ID)
  query = query.Filter("ApprovalStatus =", 1)
  if _, err := db.client.GetAll(ctx, query, &edits); err != nil {
    //err checking
  }
  tournament.Edits = edits // I guess this is wrong way to do it?
  return &tournament, nil
}

Would this work?

答案1

得分: 1

你可以创建一个新的实体来表示比赛的“编辑”操作。顺便说一下,我不是一个“datastore”用户,所以我不确定这是否是你对实体建模的方式,但是对于大多数数据库来说,基本思路是相同的:

type Tournament struct {
    ID          int64   `datastore:"-"`
    MDContent   []byte  `datastore:",noindex"`
    Name        string
    URL         string
    DateCreated int64
    CreatedBy   string
    DateUpdated int64
    UpdatedBy   string
    Edits       []TournamentEdit
}

type TournamentEdit struct {
    ID             int64   `datastore:"-"`
    MDContent      []byte  `datastore:",noindex"`
    DateCreated    int64
    CreatedBy      string
    ApprovalStatus int64 // 0=待决定, 1=已批准, 2=已拒绝, 3=已终止
    ApprovalBy     string
}

这样你就可以在队列中拥有来自不同用户的多个编辑,对特定的编辑进行CRUD操作,并且可以根据它们的状态进行筛选。

英文:

One thing you could do is to simply create a new entity that would represent the edit of a tournament. By the way, I'm not a datastore user so I'm not sure if this is how you would model the entities but the general idea is the same for most, if not all, databases:

type Tournament struct {
	ID          in64   `datastore:"-"`
	MDContent   []byte `datastore:",noindex"`
	Name        string
	URL         string
	DateCreated int64
	CreatedBy   string
	DateUpdated int64
	UpdatedBy   string
	Edits       []TournamentEdit
}

type TournamentEdit struct {
	ID             in64   `datastore:"-"`
	MDContent      []byte `datastore:",noindex"`
	DateCreated    int64
	CreatedBy      string
	ApprovalStatus int64 // 0=to be decided, 1=approved, 2=rejected, 3=discontinued
	ApprovalBy     string
}

This should allow you to have multiple edits from different users in the queue, CRUD a specific edit, and or filter edits by their status.

huangapple
  • 本文由 发表于 2017年4月18日 20:45:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/43472580.html
匿名

发表评论

匿名网友

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

确定