重新排序存储在Firebase

时间:2017-09-25 05:16:03

标签: firebase react-redux

我目前正在制作一个构建调查问卷的界面。问卷中的每个问题都存储在Firebase中,结构如下:

questions
   | - {key}
         | - lastModified // <-- When the question was created, last updated
         | - position // <-- The position in which the question appears on frontend
         | - question // <-- Question text content
         | - uid // <-- The unique key with which it is saved to firebase

   /* ... */
   /* Repeat for n questions! */
   /* ... */

管理员可以添加,删除,更新和重新排序问题。

当管理员删除问题时,我必须增加已移除问题下所有问题的位置值。

我接近这个的方法是修改我本地存储的列表副本(在我的情况下,克隆存储在Redux状态的数组),执行必要的调整,然后将其推送到firebase,覆盖现有的&#39;问题& #39;数据集。

这是我的代码:

// Remove question action creator
export function removeQuestion(key, questions) {

  return (dispatch) => {
    dispatch({type: REMOVE_QUESTION});

    const updatedQuestions = questions.filter((question) => {
      return !(question.uid === key); // I remove the target item here.
    }).map((question, index) => {
      return {
        lastModified: question.lastModified,
        position: index, // I update the position of all other items here.
        question: question.question,
        stageId: question.stageId,
        uid: question.uid
      };
    });

    questionsRef.set(updatedQuestions) // And then I save the entire updated dataset here.
    .then(() => dispatch(removeQuestionSuccess(key)))
    .catch(error => dispatch(removeQuestionError(key, error)));
  };
}

但是,有没有更好的方法呢?

2 个答案:

答案 0 :(得分:1)

您可以解决此问题的一种方法是使用浮点数来表示位置而不是实际的序数整数。然后,当您需要重新订购,而不是重新保存所有不同的位置时,只需在您之间移动的两个项目之间取中点。

这样,当你删除一个项目时,你可以只保留其他值,因为position是有序但不是有序的。

一个例子(项目是字母,位置是数字):

A: 1, B: 2, C: 3, D: 4

-> move D between A and B

A: 1, D: 1.5, B: 2, C: 3

-> move C between D and B

A: 1, D: 1.5, C: 1.75, B: 2

-> remove D

A: 1, C: 1.75, B: 2

答案 1 :(得分:1)

这是我选择的解决方案。我所做的是:

  • 不再在本地存储作为数组的列表(在我的情况下是Redux状态),将其存储为从Firebase中提取的对象,只要需要进行变异就将其转换为数组。
  • 使用数组,删除指定的项目(我使用了Array.Filter()
  • 映射数组,使用新位置更新每个项目(使用地图索引)
  • 在将数据推回Firebase之前将数组解析回对象

这是我编写的代码的通用版本,因此可能会应用于任何项目列表:

export function removeItem(key, items) {
  return (dispatch) => {

    dispatch({type: REMOVE_ITEM});

    // Convert items object (from state) into an array for easier manipulation
    const itemsArr = items ? Object.keys(items).map(key => items[key]) : [];

    const updatedItems = itemsArr.filter((item) => {
      // Filter out the item that needs to be removed
      return !(item.uid === key);
    }).map((item, index) => {
      // Update new position for remaining items
      return {
        lastModified: item.lastModified,
        position: index,
        content: item.content,
        uid: item.uid
      };
    });

    // Parsing array back into obj before pushing to Firebase
    let updatedItemsObj = {};
    updatedItems.forEach(item => {
      updatedItemsObj[item.uid] = item;
    });
    itemsRef.set(updatedItemsObj)
    .then(() => dispatch(nextAction(...)))
    .catch(error => dispatch(errorAction(key, error)));
  };
}