グラフDB ガンマン時計


グラフDB で、ガンマン時計です。

グラフDBは、データをグラフの形で保持するデータベースです。

  • ノードに情報(プロパティ)を保持できる
  • ノード間の関係(リレーション)を表現できる
  • エッジにも情報(プロパティ)を保持できる


neo4j (GraphenDB)

  • heroku で 無料の neo4j(クラウド用のneo4jをGraphenDBという)を利用できるので、 試してみました。
    https://hobby-lkdponijinkogbkeomknimel.dbs.graphenedb.com:24787/browser/
    ※パスワードあり

  • cypherという独自言語でアクセスをします。
    グラフ構造を意識したアクセス言語です。
    https://www.creationline.com/lab/7685
    • CREATE: ノードやリレーションを生成する
    • MERGE: ノードやリレーションを生成/更新する
    • SET: ノードやリレーションのプロパティを設定/変更 する
    • MATCH: ノードやリレーションを検索する
    • DELETE: ノードやリレーションを削除する
  • CypherによるグラフDBのアクセス例
    • ノードの生成(CREATE)
      ・ガンマン時計(Gunclock)
      CREATE
       (g1: Gunclock { id: 1, size: 15, color: "#ffffcc" }),
       (g2: Gunclock { id: 2, size: 32, color: "#ccffff" })
      

      ・都市(City)
      CREATE
       (c1: City { name: "Tokyo" } ),
       (c2: City { name: "Shanghai" } ),
       (c3: City { name: "Sydney" } ),
       (c4: City { name: "Moscow" } ),
       (c5: City { name: "Berlin" } ),
       (c6: City { name: "Paris" } ),
       (c7: City { name: "London" } ),
       (c8: City { name: "Cairo" } ),
       (c9: City { name: "NewYork" } ),
       (c10: City { name: "LosAngeles" } ),
       (c11: City { name: "Sao_Paulo" } )
      

      ・キャスト(Cast) [長針短針のデザイン用]
      CREATE
        (c1: Cast { name: "gunman", 
         text:[
            "** __ *", 
            " _|__|_",
            "b (@@) ",
            " V|~~|>",
            "* //T| "
         ] }
        ),
        (c2: Cast { name: "uma", 
         text:[
            "__AA  **",
            "| 6 |__P",
            "~~|    l",
            "*/_/~l_l"
         ] }
        ),
        (c3: Cast { name: "gunman2", 
         text:[
            "** __ *",
            " _|__|_",
            "  (xx; ",
            " /|~~|>",
            "P //T| "
         ] }
        ),
        (c4: Cast { name: "oni", 
         text:[
            "/| A_A  ",
            "|||-.-| ",
            "||_|-/_ ",
            "||. ~. |"
         ] }
        )
      
    • 項目(例えばid)による検索(MATCH)
      MATCH ( g: Gunclock { id: 2 } ) RETURN g
      
    • リレーションの生成(MATCH+CREATE)
      MATCH( g: Gunclock { id: 1 } )
      MATCH( c: City { name: "Tokyo" } )
      MATCH( c1: Cast { name: "gunman" } )
      MATCH( c2: Cast { name: "uma" } )
      CREATE (g)-[:city]->(c)
      CREATE (g)-[:shortHandCast]->(c1)
      CREATE (g)-[:longHandCast]->(c2)
      
    • プロパティの変更(MATCH+SET)
      MATCH ( g : Gunclock {id: 2}) 
      SET g.size=20
      SET g.color="#ccffcc"
      
    • ノードの削除(MATCH+DELETE)
      先にリレーションをすべて消す(DELETE)必要あり
      MATCH ( g:Gunclock {id: 2} )
      MATCH (g)-[r]->()
      DELETE r
      DELETE g"
      
    • リレーションの変更(MATCH+DELETE+MERGE)
      DELETEせずにMERGEだとリレーションが追加される
      MATCH ( g : Gunclock {id: 2}) 
      MATCH (g)-[r]->() 
      DELETE r
      
      MATCH ( c:City{name: "Tokyo"} ) 
      MATCH ( shcast:Cast {name: "oni"} ) 
      MATCH ( lhcast:Cast {name: "gunman2"} ) 
      
      MERGE (g)-[:city]->(c) 
      MERGE (shcast)<-[:shortHandCast]-(g)-[:longHandCast]->(lhcast)
      
      RETURN g
      
  • APOCというライブラリを導入すると、cyperの便利関数が追加される。
    • uuidの利用(apoc.create.uuid())
      CREATE ( g:Gunclock {uuid: apoc.create.uuid(), size: 22, color: "#8888ff"} )
      
    • 項目(例えばuuid)による検索(MATCH)
      MATCH (g:Gunclock {uuid: "c52af318-c351-4e89-99c0-da8cad143898"} ) RETURN g
      


GraphQLサーバ(apollo)

ガンマン時計のGraphQLサーバ (@heroku)

github : gunclock-apollo-express

  • apollo というライブラリで、GraphQLのサーバを構築することができます。
  • express 用のライブラリ(apollo-server-express)を利用しました。
  • neo4jのアクセス(cypherとのつなぎ)は、neo4j-graphql-js。
  • express の apps.js で実装です。
  • GraphQLによるグラフDBのアクセス例
    • 参照 (all gunclocks)
      ・ノードを全取得
        { 
          Gunclock {
            _id,
            uuid,
            size,
            color
          }
        }
      
      • 結果
        {
          "data": {
            "Gunclock": [
              {
                "_id": "2",
                "uuid": "6e854d99-57ca-4d78-bda2-80ea1e15721f",
                "size": 22,
                "color": "#cc88cc"
              },
              {
                "_id": "40",
                "uuid": "b786af21-fd75-470f-b3f3-f8f3022f6450",
                "size": 25,
                "color": "#88ffff"
              },
              {
                "_id": "61",
                "uuid": "c52af318-c351-4e89-99c0-da8cad143898",
                "size": 16,
                "color": "#ffff88"
              },
              {
                "_id": "62",
                "uuid": "5112845b-a3e6-415c-953a-afae40096e7d",
                "size": 77,
                "color": "#ff0000"
              }
            ]
          }
        }
        

      ・ノードを全取得(リレーションも含めて全取得)
        { 
          Gunclock {
            _id,
            uuid,
            size,
            color,
            city{name},
            shortHandCast{text},
            longHandCast{text}
          }
        }
      
      • 結果
        {
          "data": {
            "Gunclock": [
              {
                "_id": "2",
                "uuid": "6e854d99-57ca-4d78-bda2-80ea1e15721f",
                "size": 22,
                "color": "#cc88cc",
                "city": {
                  "name": "Tokyo"
                },
                "shortHandCast": {
                  "text": [
                    "** __ *",
                    " _|__|_",
                    "b (@@) ",
                    " V|~~|>",
                    "* //T| "
                  ]
                },
                "longHandCast": {
                  "text": [
                    "__AA  **",
                    "| 6 |__P",
                    "~~|    l",
                    "*/_/~l_l"
                  ]
                }
              },
              {
                "_id": "40",
                "uuid": "b786af21-fd75-470f-b3f3-f8f3022f6450",
                "size": 25,
                "color": "#88ffff",
                "city": {
                  "name": "Sydney"
                },
                "shortHandCast": {
                  "text": [
                    "** __ *",
                    " _|__|_",
                    "  (xx; ",
                    " /|~~|>",
                    "P //T| "
                  ]
                },
                "longHandCast": {
                  "text": [
                    "/| A_A  ",
                    "|||-.-| ",
                    "||_|-/_ ",
                    "||. ~. |"
                  ]
                }
              },
              {
                "_id": "61",
                "uuid": "c52af318-c351-4e89-99c0-da8cad143898",
                "size": 16,
                "color": "#ffff88",
                "city": {
                  "name": "NewYork"
                },
                "shortHandCast": {
                  "text": [
                    "__AA  **",
                    "| 6 |__P",
                    "~~|    l",
                    "*/_/~l_l"
                  ]
                },
                "longHandCast": {
                  "text": [
                    "/| A_A  ",
                    "|||-.-| ",
                    "||_|-/_ ",
                    "||. ~. |"
                  ]
                }
              },
              {
                "_id": "62",
                "uuid": "5112845b-a3e6-415c-953a-afae40096e7d",
                "size": 27,
                "color": "#ff0000",
                "city": {
                  "name": "Paris"
                },
                "shortHandCast": {
                  "text": [
                    "** __ *",
                    " _|__|_",
                    "  (xx; ",
                    " /|~~|>",
                    "P //T| "
                  ]
                },
                "longHandCast": {
                  "text": [
                    "** __ *",
                    " _|__|_",
                    "b (@@) ",
                    " V|~~|>",
                    "* //T| "
                  ]
                }
              }
            ]
          }
        }
        
    • 参照 (レコード指定(uuid検索))
        { 
          Gunclock(
            uuid:"c52af318-c351-4e89-99c0-da8cad143898"
          )
          {
            _id,
            uuid,
            size,
            color,
            city{name},
            shortHandCast{text},
            longHandCast{text}
          }
        }
      
    • 生成
        mutation {
          createGunclock(
            size:16,
            color:"0xffff88",
            cityName:"Tokyo",
            shortHandCastName:"gunman",
            longHandCastName:"uma"
          )
          {
            _id,
            uuid,
            size,
            color,
            city{name},
            shortHandCast{text},
            longHandCast{text}
          }
        }
      
    • 更新 (レコード指定(uuid検索))
        mutation {
          updateGunclock(
            uuid:"c52af318-c351-4e89-99c0-da8cad143898"
            size:25,
            color:"0x88ffcc",
            cityName:"London",
            shortHandCastName:"oni",
            longHandCastName:"gunman2"
          )
          {
            _id,
            uuid,
            size,
            color,
            city{name},
            shortHandCast{text},
            longHandCast{text}
          }
        }
      
    • 削除 (レコード指定(uuid検索))
        mutation {
          deleteGunclock(
            uuid:"c52af318-c351-4e89-99c0-da8cad143898"
          )
          { _id }
        } 
      


【フロント react】

グラフDB ガンマン時計 (@heroku)

github: gunclocks-graphdb-react

herokuで公開
node.js の フロントエンド向けフレームワーク react です。

  • フロントをreact。
    • 実行すると Node.js のサーバとなり動作します
    • クライアントで実行をするJavaScriptを生成します
    • ブラウザ側にdownloadして動作し、 ユーザの入出力(ブラウザインタフェース)を管理します
    • ページに「state」という情報を保持して、 ページをレンダリングします。
    • JSXという言語(Javascript拡張)でhtmlを生成します
    • SPA(Single-Page-Application)の記述が楽、な気がします
    • apolloのclientもあるが、うまく行かなかったので、今回は、http呼び出しでjsonを取得し、jsonを解析しています。


[ ガンマンのページへ戻る ]