Firebase数据库关系问题-为用户存储所选项目

时间:2018-06-26 18:37:16

标签: firebase nosql google-cloud-firestore real-time

因此,我现在绝对是一个火力发烧友,并且通常只是一个noSql noob。这是我的问题。

我有一组这样的数据

-items
 --id1
   theData
 --id2
   theData
 --id3
   theData
 --id4
   theData      

我有一些用户将选择此数据的一个子集。现在示例用户A和用户B。

-itemSelected
 ---UserA
    ---Id1  (different than item key)
       theData from items id1 (with items id1 key included so I can reference)
    ---Id2  (different than item key)
       theData from items id3 (with items id3 key included so I can  reference)
  ---UserB
    ---Id1 (different than item key)
       theData from items id1 (with items id1 key included so I can reference)
    ---Id2 (different than item key)
       theData from items id4 (with items id4 key included so I can reference)

具有更结构化的标准化SQL背景,我觉得我要解决这个错误。在开发过程中,我看到如果在哪里更改项目数据,那么我的用户数据文档中将有不良数据。我到目前为止在我的项目中进展不大,我想用firebase实时db和id完成它的项目并不多,我想解决这个noSql问题。所以我应该如何设置缺少或做错了什么。还是我应该切换到Firestore,如果可以,那该如何解决我的问题。

仅供参考-之所以需要参考,是因为有时需要比较这两个数据,这样我才能正确显示表格。我认为键是比较数据的自然方法。同样,我在那里可能非常注重SQL。

希望有一些noSql或firebase专家可以提供一些解决方案。谢谢!

更新

基于响应者Bryan Massoth,我认为这是有目的的新结构。

-items
 --id1
   theData
 --id2
   theData
 --id3
   theData
 --id4
   theData      

我有一些用户将选择此数据的一个子集,但不存储数据的副本,而仅存储项id的键值和布尔值true(用于选择)。现在示例用户A和用户B。

-itemSelected
 ---UserA
    ---Id1  (different than item key)
       id1KeyFromItems: "True"
    ---Id2  (different than item key)
       id3KeyFromItems: "True"
  ---UserB
    ---Id1 (different than item key)
       id1KeyFromItems: "True"
    ---Id2 (different than item key)
       id4KeyFromItems: "True"

所以我可能看到的最后一个问题是我当前正在另一个表中显示用户选择的数据,这就是为什么我最初将所有子选择的数据写入firebase中的userA或UserB的配置文件的原因。所以我可以轻松地订阅它并从那里显示它。如果我走了布尔路线,如果我仅存储密钥,我如何仅显示用户A选择的项目中的数据?

2 个答案:

答案 0 :(得分:1)

很多结构都取决于您将如何使用数据。我会说您的大多数结构都是正确的。我唯一要做的就是不要复制itemSelected/{userId}下的数据。如果已将实际的itemId设置为true,则只需将其设置为-itemSelected -UserA -Id1 (same as items Id1): true -Id2 (same as items Id2): true

itemSelected

这会增加额外的负载,但是可以通过良好的UI / UX设计将其隐藏。这将允许搜索已选择特定项目的用户。它还可以确保数据还不错。

关于存储在items中的数据的“子集”注释:如果要引用的特定项目的数据是items表中该项目的数据存储子集,并且出于安全性考虑(即class TaskItem { private int milisecods = 200; DateTime Now { get { return DateTime.Now; } } public TaskItem() { this.Created = Now; } private DateTime Created; public string EntryId { get; set; } public bool OutDated { get { return this.Created.AddMilliseconds(milisecods) > Now; } } } List<TaskItem> TaskItemsList = new List<TaskItem>(); private void TaskItems_ItemChange(object Item) { this.TaskItemsList.RemoveAll(x => x.OutDated); MailItem element = Item as MailItem; if (element != null) { if (element.FlagStatus == OlFlagStatus.olFlagComplete) { if (this.TaskItemsList.Any(x => x.EntryId == element.EntryID) == false) { this.TaskItemsList.Add(new TaskItem { EntryId = element.EntryID }); new WcfClient().ProcesOutlookTask(TaskActionType.Finished); } } } } 部分中的某些数据不应被用户看到),那么我建议保留所有内容,而只是创建Firebase Function来保持记录“最终”保持一致。 / p>

答案 1 :(得分:0)

所以我经历了这个。布赖恩让我参与其中,所以我支持他的回答,但我在此处发布了完整答案,以便其他人可以从中受益。我试图将最初的问题尽力解决,但我意识到这很困难,这可能不是最佳论坛,但是我在其他任何地方都找不到答案,我有特定的用例,现在可以与我分享更多的用例码。

用例进行汇总。我将物品存储在Firebase中。用户将要从项目中进行选择。我需要存储他们选择的内容,但要使数据尽可能保持可维护性。布赖恩建议只存储可以使用的密钥。但是我在用户界面中显示了用户在div中选择的内容,因此本质上,如果我不将数据存储在个人资料中,则需要基于存储的键对原始项目数据进行过滤(我在bryan发表后意识到了这一点)在我的用户个人资料中。

我是一个React应用程序,所以我连接了Reselect并使用Selectors加载了我与过滤器匹配的2个数据部分,并通过组件中的redux将它们连接起来。

如果您是选择器的新手,那么这段视频对我很有帮助,并且可以连接该解决方案。

https://www.youtube.com/watch?v=XCQ0ZSr-a2o

此处用于选择器的相关代码。基本上,您可以获取项目列表和userSelectedItems列表(仅是键/ ID)并进行比较。如果它们相同,则对于新的过滤列表,filter的值为true。

这是我的选择器。

export function getUser(state) {
   return state.User;
 }

export function getUserItemsList(state) {
  return getTeam(state).list;
 }


export function getItemsList(state) {
 return state.Items.list
}

export function getUserItemsFilter(userItems, items) {

  const selectedItems = items.filter(
    item => userItems.some(userItem => userItem.itemKey === item.key));
   return selectedItems
 }

 export const ItemSelector = createSelector(
  getUserItemsList,  //pick off piece of state
  getItemsList,  //pick off piece of state
  getUserItemsFilter //last argument that runs for Item Selector, do processing here
 );

回到组件中,然后导入创建的选择器,并将其连接到mapStateToProps。

 const mapStateToProps = state => {
  return {
   itemsSelected: ItemSelector(state),
   }
}


const mapDispatchToProps = Object.assign(
  {},
  userActions,
);

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(UserPage));

现在ItemsSelected将被映射为状态到您的React组件。这是过滤后的Items数组,仅包含与您在用户个人资料中存储的键具有相同键的值条目。

这确实解决了我原来的问题,即我的数据在Firebase中更易于维护,因为所有数据都在项目中,而不是在用户个人资料中重复。谢谢React中的Immutable和Reselect。他们是为这个东西而建造的。希望这对其他人有帮助。首先,意识到这对于堆栈来说有点宽泛,希望代码可以帮助改进用例,并使其对现在的其他用户有价值。

最后一次。我的数据现在在Firebase中看起来像这样。

物品

-items
 --id1
   theData
 --id2
   theData
 --id3
   theData
 --id4
   theData      

UserProfile

-itemSelected
 ---UserA
    ---Id1  (different than item key)
       "id": "id1KeyFromItems"
    ---Id2  (different than item key)
       "id": "id3KeyFromItems"
  ---UserB
    ---Id1 (different than item key)
       "id": "id1KeyFromItems"
    ---Id2 (different than item key)
       "id": "id4KeyFromItems"

我的高级数据库功能总是在firebase中创建新的唯一键。我不想仅针对此解决方案进行更改。这可以正常工作,并使我的应用程序中的CRUD一切运行相同。