1

私は webApp のような Excel に取り組んでおり、ユーザーが自由に行を挿入できる機能を実装したいと考えています。フロントエンドを簡単に変更して、スプライスと選択した行 ID によって挿入する場所を視覚化できますが、バックエンドはデフォルトで _id と順序を生成する mongoDB を使用しています。この問題を解決するために、前と後の Id を生成し、前と後の間に newId を作成します。

if (this.state.insertIndex !== undefined && this.state.insertIndex !== 0 && this.state.insertIndex !== rows.length - 1) {
  const after = parseInt(rows[Math.max(this.state.insertIndex - 1, 0)]._id.toString().substring(0, 8), 16) * 1000;
  const before = parseInt(rows[Math.min(this.state.insertIndex + 1, rows.length - 1)]._id.toString().substring(0, 8), 16) * 1000;
  const timestampAsInteger = Math.floor(Math.random() * (after - before) + before);
  newId = Math.floor(timestampAsInteger / 1000).toString(16) + "0000000000000000";
}

注: insertIndex の初期未定義、セル選択時の setState、行削除後の未定義へのリセット

ただし、このアルゴリズムには考慮されていない多くのエッジケースがあるようですが、より堅牢にする経験がある人はいますか? またはエッジケースに関する提案はありますか?

既知の問題:

  • 行[0]を選択したときの間違った動作
  • dup _id の生成 (理由がわからない)

その他のアイデア

  • _id を生成する代わりに、ユーザーが見るように localStorage render によって行の状態を保存する方が簡単でしょうか。
  • ここにリンクの説明を入力しましたが、理解できませんでした。解決策があるかどうか誰か説明してもらえますか?

何かご意見は?どうもありがとう

4

1 に答える 1

0

数日後、私はこの回避策を見つけました。_ids のリストを維持する代わりに、私のメソッドには制限があります。

これは、前後のタイムスタンプに従って独自の mongo _id を生成するコードです。

    let newId;
    let canInsert = true;
    if (this.state.insertIndex !== undefined) {
      if (this.state.insertIndex == 0 && rows.length >=2) {
        const before = parseInt(rows[Math.max(this.state.insertIndex, 0)]._id.toString().substring(0, 8), 16) * 1000
        const after = parseInt(rows[Math.min(this.state.insertIndex + 1, rows.length - 1)]._id.toString().substring(0, 8), 16) * 1000;
        if (after - before > 1000) {
          const timestampAsInteger = Math.floor(Math.random() * (after - before + 1) + before);
          if (timestampAsInteger - before > 1000) {
            newId = Math.floor(timestampAsInteger / 1000).toString(16) + "0000000000000000";
          } else {
            canInsert = false;
          }
        } else {
          canInsert = false;
        }
      } else if (this.state.insertIndex < rows.length - 1) {
        const before = parseInt(rows[Math.max(this.state.insertIndex, 0)]._id.toString().substring(0, 8), 16) * 1000
        const after = parseInt(rows[Math.min(this.state.insertIndex + 1, rows.length - 1)]._id.toString().substring(0, 8), 16) * 1000;
        if (after - before > 1000) {
          const timestampAsInteger = Math.floor(Math.random() * (after - before + 1) + before);
          if (timestampAsInteger - before > 1000) {
            newId = Math.floor(timestampAsInteger / 1000).toString(16) + "0000000000000000";
          } else {
            canInsert = false;
          }
        } else {
          canInsert = false;
        }
      }
    }

上記のコードは非常に読みにくいことは理解していますが、特に newId 生成メソッドが原因で多くのエッジ ケースがあり、2 つのタイムスタンプの間隔が少なくとも 1000 を超える必要があるという制限があり、そうしないと問題が発生します。

フェッチでは、newId が生成されているかどうかを確認する必要があります。生成されていない場合は、最後の行に追加します

      let index = this.state.insertIndex == undefined? Math.max(rows.length, 0): Math.max(this.state.insertIndex + 1, 0);
      json["value"] = index;
      rows = canInsert ? update(rows, {$splice: [[index, 0, json]]}): update(rows, { $push: [json] });
      if (canInsert) {
        this.showMessage("The project name cannot be empty");
      } else {
        this.showMessage("Impossible to insert, add last instead");
      }

バックエンドで、_id を newId に設定します

if (req.body.newId) {
    initialData['_id'] = req.body.newId;
}

この機能の最も難しい部分は、考えられる非常に多くのエッジ ケースをキャッチすることです。また、2 つの既存の行が密接に生成されない可能性があるという挿入行の制限があります。また、アプリがより多くのユーザーでスケールアップし続けると、問題が発生します。ただし、それは、より小さなユーザー グループに対しては機能し、必要に応じてオプション機能として機能します。

将来、よりユニークな ID ジェネレーターを開発できれば、無制限に挿入できる可能性があります。私が調査する限り、誰もこのようなことを思いついたことはありませんでしたが、物事を理解するのに何日もかかりました. この調査結果により、調査にかかる時間を節約できることを願っています。

于 2019-03-21T20:26:39.017 に答える