如何将项目存储在特定位置的firebase列表中

时间:2018-02-09 07:52:01

标签: javascript list firebase firebase-realtime-database

我有一个这样的清单:

{ 
  randomFirebaseGeneratedUID: {position: 0, someData: ''},
  randomFirebaseGeneratedUID: {position: 1, someData: ''},
  randomFirebaseGeneratedUID: {position: 2, someData: ''},
  randomFirebaseGeneratedUID: {position: 3, someData: ''},
  randomFirebaseGeneratedUID: {position: 4, someData: ''},
}

现在我想添加一个新项目,例如,在位置1和2之间

我很难找到一个干净,正确的方法。我现在想出的是:

export const addAtListPositionHelper = (list, payload) => {
  Object.keys(list)
    .filter(key => list[key].position > payload.position)
    .forEach(key => {
      list[key].position = list[key].position + 1
    })
  list.push().set(payload)
  return list
}

export function addAtListPosition(contentId, payload) {
  const db = getFirebaseInstance().database()
  db.ref(`${contentId}`).transaction(list => addAtListPositionHelper(list, payload))
}

有效负载看起来像:{p: 2, someData: ''}

这个问题是我不能按照代码中的内容来推送有效负载,因为列表实际上是一个对象,这些对象的id是从firebase生成的UID。

当然我可以自己生成UID,但是对我来说看起来有些麻烦,因为我有一些由firebase生成的UID和一些由我自己生成的UID。

我想到的另一种方法是先推送项目然后再进行排序,但这可能会导致短时间内数据不一致。

是否真的没有更好的方法来处理我认为非常常见的用例?

1 个答案:

答案 0 :(得分:0)

这听起来很混乱,现在正处于竞争状态。对任何数据库进行重新索引都是一项昂贵的操作,尤其是Firebase,因为它具有NoSQL / Realtime特性。

我能够快速想到的唯一方法是在整个列表中使用事务。这将起作用,但会严重损害此代码的可伸缩性。

问题源于这样一个事实,即你希望你的位置是连续的整数,这是难以扩展的。实际上,最古老的Firebase博客文章之一就是建议的:Best Practices: Arrays in Firebase

因此,为了使此操作更具可伸缩性,您必须远离作为顺序整数的位置。我知道两种方法:

  1. 使它们成为非连续的

  2. 将它们设为非整数

  3. : - )

    使它们不顺序

    另一种方法是在生成新文档时留出插入项目的空间。例如。如果你将索引分开如下:

    { 
      randomFirebaseGeneratedUID: {position: 0, someData: ''},
      randomFirebaseGeneratedUID: {position: 10, someData: ''},
      randomFirebaseGeneratedUID: {position: 20, someData: ''},
      randomFirebaseGeneratedUID: {position: 30, someData: ''},
      randomFirebaseGeneratedUID: {position: 40, someData: ''},
    }
    

    然后10到20之间的项目可以获得位置15.这实际上很常见,并且大大减少了重新索引所有项目的需要。

    使它们成为非整数

    如果您的头寸可以是非整数,您将永远不必重新索引。然后在1和2之间插入一个简单的1.5。并且通过浮点数的分辨率,您很快就不会用尽“位置”。

    这实际上是我最近需要移动/重新排序/插入文档时采用的方法。