JSONデータベースの完全な履歴を問い合わせる


に貢献するCoreSvelte based Frontend
以下のダイアグラムはsirixDBの変更イベントを通して状態の展開を表します.

導入


まず第一に、ほとんどのJSONファイルを扱うデータベースシステムを必要としないでしょう.
ただし、データのGBSを管理して問い合わせを行う場合は、データベースシステムを使用する必要があります.
通常、データベースシステムは、データの完全な履歴を維持するように設計されていません.しばしば、システムは変更中にデータを上書きするか、短時間データを保持する.後者は通常トランザクションのために起こります.このように、ガベージコレクターはすべての読み込みトランザクションが終了するまで待ちます.その後、古いデータを削除することができます.
代わりに、SIRIXDBは巨大な永続的な木を作ります.これはデータを追加するだけです.すべての改正はインデックスされます、その一方で、改正はページ断片を変えません.Gitのようにそれを考えますが、サブファイルレベルで.持続的な木もHaskellと閉鎖のような機能的言語で一般的です.トランザクションのコミットは、ページを縦断的に横断してページをシリアル化します.

通常、これらの永続的なメモリ構造を永続的なデバイスにマッピングすることによって、書き込み増幅が追加される.しかし、我々は主な文書店のためにキーつきのtrieを使います.したがって、B木のように構造変化は起こらない.さらに,データページとストア変数サイズページフラグメントをバージョンアップする新しいスライディングスナップショットアルゴリズムを開発した.したがって、いくつかの変更されたレコードだけが新しいページフラグメントに書き込まれます.メモリ内のページを再構成すると、ランダムにランダムな位置からページフラグメントのスライディングウィンドウを読み取ることができます.
高速、ランダム、細かい粒状の読み込みのための要件のために、バイトアドレス可能なNVMとして近代的なハードウェアが良いパフォーマンスに不可欠になります.
sirixDBはJSONデータをバイナリ形式で格納しますが、各トランザクションは特定のリビジョンにバインドされます.現在、リソース上のN読み取り専用トランザクションは、リソース上の1つの読み書きトランザクションと共存することができる(JSONデータを表す).
このコード化は、親から最後の子ノードへのポインタを最近導入したことを除いて、次のようになります.

クエリデータ


システムはXQuery 3.0プロセッサを使ってXMLとJSONデータの両方を処理します.
JSONファイルを特定のディレクトリからインポートできます.
jn:load('mycol.jn', (), io:ls('/home/johannes/json-data', '\\.json$'))
データベース名を作成しますmycol.jn といくつかのリソース.
また、データベース内のいくつかのリソース内にJSON文字列を格納することもできます.
jn:store('mycol.jn',(),('["bla", "blubb"]','{"foo": true}'))
JSON文字列を置き換えるときにtrue and false with true() and false() だけでなくnull with jn:null() .
データベースコレクションを次のように照会できます.
for $doc in jn:collection('mydocs.col') return $doc
または、データベース内の特定のリソースをオープンしたい場合は、以下のようにします.
jn:doc('mydocs.col', 'myresource1')
さらに、リソースを更新できます.以下の小さなJSONファイルがあるとしましょう.
{
  "foo": [
    "bar",
    null,
    2.33
  ],
  "bar": {
    "hello": "world",
    "helloo": true
  },
  "baz": "hello",
  "tada": [
    {
      "foo": "bar"
    },
    {
      "baz": false
    },
    "boo",
    [],
    {}
  ]
}
JSONオブジェクトを挿入できます.
insert json { "name": "keyword" } into jn:doc('mydocs.col', 'myresource1')=>tada=>foo
オブジェクトフィールド名を=> 演算子.それも、配列にドリルダウンし、フィールド名の値を見つけることができます.
更新操作はフィールド名と追加された値で新しいリビジョンを作成します.例えば
jn:doc('mydocs.col', 'myresource1')=>tada[[0]]
フィールド名の配列値の最初のオブジェクトを選択しますtada .
{
  "foo": "bar",
  "name": "keyword"
}
我々は暗黙のうちに修正2を問い合わせる.代わりにRevision 1を問い合わせても、古いJSONオブジェクトを取得します.
jn:doc('mydocs.col', 'myresource1', 1)=>tada[[0]]
関数の3番目の引数として指定したことに注意してください.出力は:
{
  "foo": "bar"
}
3番目のパラメータに数値を与える代わりに、タイムスタンプで特定のリビジョンを開くこともできます(ここでは、特定のリソースが2018年4月にどのように見えたかを確認します).
jn:open('mydocs.col', 'myresource1', xs:dateTime(\"2018-04-01T05:00:00-00:00\"))
関数オープンリビジョンでは、2つのポイント間のリソースのすべてのリビジョンを読み込むことができます.
jn:open('mydocs.col', 'myresource1', xs:dateTime(\"2018-04-01T05:00:00-00:00\", xs:dateTime(\"2019-04-01T05:00:00-00:00\"))
次のクエリは、配列の値にオブジェクトを挿入します=>foo 次の項目として
insert json { "name": "keyword" } into jn:doc('mydocs.col', 'myresource1')=>foo at position 1
使用
jn:doc('mydocs.col', 'myresource1')=>foo 
出力を取得します.
[
  "bar",
  {
    "foo": "bar"
  },
  null,
  2.33
]
同様に、私たちはJSON値を
replace json value of jn:doc('mydocs.col', 'myresource1')=>tada[[0]] with "yes"
または値を削除する
delete json jn:doc('mydocs.col', 'myresource1')=>tada[[0]]
REST - APIを通して質問を提出するならば、あなたは最初に認可されなければなりません.このように、Gitのように、改正も著者の名前とUUIDを保存します.
特定の修正を行った著者名を取得するには、次の手順に従います.
jn:author-name(jn:doc(...))
UUIDを取得するには、次の手順に従います.
jn:author-uuid(jn:doc(...))
プロジェクトフィールドもできます.
jn:doc('mydocs.col', 'myresource1')=>bar{hello} 
出力します.
{
  "hello": "world"
}

タイムトラベル機能


また、時間旅行のクエリの束を使用することができます.以下の関数は、JSON項目の異なるバージョンを取得します.
jn:future($item as json-item(), $includeSelf as xs:boolean) as json-item()*
JSONアイテムを選択する機能は、将来または将来または自己.最初のパラメータはコンテキスト項目です.2番目のパラメータは、現在の項目が結果に含まれているかどうかを示します.
jn:past($item as json-item(), $includeSelf as xs:boolean) as json-item()*
過去または過去または自己のJSONアイテムを選択するための機能.最初のパラメータはコンテキスト項目です.番目のパラメータは、現在の項目が結果に含まれているかどうかを示します.
jn:all-times($item as json-item()) as json-item()+
すべての改訂でJSON項目を選択する機能.
jn:first($item as json-item()) as json-item()?
最初の改正でJSON項目を選択するための関数.
jn:last($item as json-item()) as json-item()?
最後の/最近の改正のJSON項目を選ぶための機能.
jn:previous($item as json-item()) as json-item()?
前の改正のJSON項目を選ぶための機能.
jn:next($item as json-item()) as json-item()?
次のリビジョンのJSON項目を選択する関数.
すべてのリビジョンで項目を取得します.
jn:history($item as json-item()) as json-item()?

拡散


もちろん、diffを取得することもできます.
jn:diff('mydocs.col', 'myresource2', 1, 3)
この関数は、myresource2 .
出力形式はJSON文字列です.
{
  "database": "json-path1",
  "resource": "shredded",
  "old-revision": 1,
  "new-revision": 3,
  "diffs": [
    {
      "insert": {
        "nodeKey": 26,
        "insertPositionNodeKey": 1,
        "insertPosition": "asFirstChild",
        "deweyID": "1.17.9",
        "depth": 2,
        "type": "jsonFragment",
        "data": "{\"tadaaa\":\"todooo\"}"
      }
    },
    {
      "delete": {
        "nodeKey": 13,
        "deweyID": "1.17.49",
        "depth": 2
      }
    },
    {
      "update": {
        "nodeKey": 15,
        "deweyID": "1.17.65",
        "depth": 2,
        "name": "tadaa"
      }
    }
  ]
}
例えば、この形式は私たちのGUI , 我々は現在Svelteに基づいて開発します.
sirixdbは1と3の改訂を比較した.さらに、異なるdiff型はinsert, delete, update and replace (後者)The insertPositionNodeKey 挿入ノードが発生するコンテキストノードですinsertPosition それが最初の子、右の兄弟、または左の兄弟として挿入されている場合を示します.
また、サブツリーをdiffし、2つの追加パラメータを指定することもできます.The root node , どちらを比較しようかdepth :
jn:diff('mydocs.col', 'myresource2', 1, 3, 7453, 2)
これはmyresource2 リソースmydocs.col データベース.しかし、今回は、そのユニークなNODEKEY 7453で示されるノードでDIFFが始まります.さらに、Diffingは2つのレベルより深い子孫をスキップしなければなりません.
を得るためにnodeKey 特定の項目のうち、以下を使用できます.
sdb:nodekey(...)

結論


sirixDBは、データの完全な履歴をクエリに強力な方法を提供しています.
インデックス構造の作成を省略しましたが、XQueryを使った二次インデックス構造を作成することもできます.
次のドキュメント(シリアル化された2つのリビジョンのsirixdbリソース)を考えてください.
{
  "sirix": [{
    "revisionNumber": 1,
    "revision": {
      "foo": ["bar", null, 2.33],
      "bar": {
        "hello": "world",
        "helloo": true
      },
      "baz": "hello",
      "tada": [{
        "foo": "bar"
      }, {
        "baz": false
      }, "boo", {},
        []
      ]
    }
  }, {
    "revisionNumber": 2,
    "revision": {
      "tadaaa": "todooo",
      "foo": ["bar", null, 2.33],
      "bar": {
        "hello": "world",
        "helloo": true
      },
      "baz": "hello",
      "tada": [{
        "foo": "bar"
      }, {
        "baz": false
      }, "boo", {},
        []
      ]
    }
  }]
}
次のコンテンツと構造体を作成できます.
let $doc := jn:doc('mycol.jn','mydoc.jn')
let $stats := jn:create-cas-index($doc, 'xs:string', '/sirix/[]/revision/tada//[]/foo/[]/baz') return {"revision": sdb:commit($doc)}
クエリに答えるには
let $result := jn:doc('mycol.jn','mydoc.jn')=>sirix[[2]]=>revision=>tada[.=>foo=>baz >= 'baa' and .=>foo=>baz <= 'brr'] return $result

さらに、XQueryの礎石であるFlowr式については言及しませんでした.暗黙の結合を持つ簡単な例
for $i in jn:doc('mycol.jn','mydoc.jn')=>paths=>"/consolidated_screening_list/search"=>get
let $j := $i=>parameters=>name
return for $k in $j
       where $k eq 'keyword'
       return { "result": $i, "nodekey": sdb:nodekey($i) }