0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

json-serverのDELETEで全てのアイテムや予期しないアイテムが削除される問題

Posted at

json-serverは非常に便利なのですが、あるアイテムを削除しようとしたときに、なぜか全てのアイテムが削除されてしまう現象に出くわしました。

TL;DR

デフォルトで設定されている外部キーのサフィックスIdと自動的に実行されるcascading deleteの組み合わせで起きる現象なので、外部キーのサフィックスを変えてやれば(一応は)解決します。

json-server db.json --fks _id

問題の再現

db.json
{
  "customers": [
    {
      "id": 1,
      "customerId": "顧客ID1",
      "name": "顧客1"
    },
    {
      "id": 2,
      "customerId": "顧客ID2",
      "name": "顧客2"
    },
    {
      "id": 3,
      "customerId": "顧客ID3",
      "name": "顧客3"
    }
  ]
}

何の変哲もないDBです。サロゲートキーidを自動生成、ナチュラルキーcustomerIdを手入力することを想定した、よくある設計です。

json-server db.json

普通にjson-serverを立ち上げます。

curl -XDELETE http://localhost:3000/customers/1

普通にid=1のアイテムを削除します。

db.json
{
  "customers": []
}

なんということでしょう、全アイテムが削除されました

原因

自動的に外部キーを設定し、自動的にcascading deleteしてしまう仕様が原因でした。

  1. デフォルトでは、Idが自動的に外部キーのサフィックスとみなされるようになっており、
  2. customerIdcustomerへの外部キーとみなされ、
  3. 任意のcustomerを削除すると、
  4. customerIdによって参照されていないcustomerはcascading deleteによって全て削除されてしまう…

ということのようです。

試しに、customerIdを外部キーと考え、以下のようにid=1id=2のアイテムがお互いを参照するようにcustomerIdを設定し、id=3を削除すると、無事にid=3のみが削除されます。

db.json
{
  "customers": [
    {
      "id": 1,
      "customerId": 2,
      "name": "顧客1"
    },
    {
      "id": 2,
      "customerId": 1,
      "name": "顧客2"
    },
    {
      "id": 3,
      "customerId": 1,
      "name": "顧客3"
    }
  ]
}

対策

外部キーのサフィックスはオプションで設定できるので、適当な値に変えてやれば解決します。

json-server db.json --fks _id

ただし、実際の外部キーのサフィックスとしてIdを利用することはできなくなってしまうので、外部参照をせずアイテムを埋め込んでおくか、apiのpayloadの設計を変える必要があります。
しかし、モックサーバーの制限に合わせて本体の設計を変えるのは、控えめに言ってもおかしな話です。
個人的には、埋め込みによる対応でモックサーバーとしての役目は十分に果たせるので、問題ないといえばないのですが。

例外的なユースケースというわけでもないと思うので、公式に対策してほしいところです。しかし、現状ではcascading deleteはドキュメントにも記載されておらず、制御する方法もありません。
issueも上がっており、従属的なアイテムのみを削除+カスケードしないフラグを追加するプルリクも上がっているのですが、もう半年近く放置されています…。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?