Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

FalkorDB

livebooks/redisgraph/falkor_db.livemd

FalkorDB

Mix.install([
  {:redisgraph, "~> 0.1.0"},
  {:kino, "~> 0.14.2"}
])

alias RedisGraph.{Node, Edge, Graph, QueryResult}

Connect to FalkorDB

{:ok, conn} = Redix.start_link("redis://falkor_db_for_livebook:6379")

Create new Graph

graph = Graph.new(%{name: "Sweets"})

Add Nodes

node = Node.new(%{
  label: "Sweet",
  properties: %{
    name: "チョコレートケーキ",
    category: "ケーキ",
    brand: "スイーツベーカリー",
    price: 450
  }
})
{graph, node} = Graph.add_node(graph, node)

graph
nodes = %{"チョコレートケーキ" => node}

{graph, nodes} =
  [
    %{
      label: "Sweet",
      properties: %{
        name: "イチゴのチーズケーキ",
        category: "ケーキ",
        brand: "チーズハウス",
        price: 520
      }
    },
    %{
      label: "Sweet",
      properties: %{
        name: "アップルパイ",
        category: "パイ",
        brand: "パイファクトリー",
        price: 400
      }
    },
    %{
      label: "Sweet",
      properties: %{
        name: "チョコチップクッキー",
        category: "クッキー",
        brand: "クッキーランド",
        price: 300
      }
    },
    %{
      label: "Sweet",
      properties: %{
        name: "ストロベリーキャンディー",
        category: "キャンディー",
        brand: "キャンディーガーデン",
        price: 100
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "小麦粉",
        type: "粉類"
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "砂糖",
        type: "粉類"
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "卵",
        type: "液体"
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "バター",
        type: "乳製品"
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "チョコレート",
        type: "粉類"
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "牛乳",
        type: "乳製品"
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "イチゴ",
        type: "フルーツ"
      }
    },
    %{
      label: "Ingredient",
      properties: %{
        name: "リンゴ",
        type: "フルーツ"
      }
    }
  ]
  |> Enum.reduce({graph, nodes}, fn entities, {acc_graph, acc_nodes} ->
    {graph, node} = Graph.add_node(acc_graph, Node.new(entities))

    nodes = Map.put(acc_nodes, entities.properties.name, node)

    {graph, nodes}
  end)

Add edges

edge = Edge.new(%{
  src_node: Map.get(nodes, "チョコレートケーキ"),
  dest_node: Map.get(nodes, "砂糖"),
  relation: "CONTAINS"
})
{:ok, graph} = Graph.add_edge(graph, edge)
graph =
  [
    {"チョコレートケーキ", "CONTAINS", "卵"},
    {"チョコレートケーキ", "CONTAINS", "バター"},
    {"チョコレートケーキ", "CONTAINS", "チョコレート"},
    {"イチゴのチーズケーキ", "CONTAINS", "小麦粉"},
    {"イチゴのチーズケーキ", "CONTAINS", "砂糖"},
    {"イチゴのチーズケーキ", "CONTAINS", "卵"},
    {"イチゴのチーズケーキ", "CONTAINS", "バター"},
    {"イチゴのチーズケーキ", "CONTAINS", "牛乳"},
    {"イチゴのチーズケーキ", "CONTAINS", "イチゴ"},
    {"アップルパイ", "CONTAINS", "小麦粉"},
    {"アップルパイ", "CONTAINS", "砂糖"},
    {"アップルパイ", "CONTAINS", "バター"},
    {"アップルパイ", "CONTAINS", "リンゴ"},
    {"チョコチップクッキー", "CONTAINS", "小麦粉"},
    {"チョコチップクッキー", "CONTAINS", "砂糖"},
    {"チョコチップクッキー", "CONTAINS", "バター"},
    {"チョコチップクッキー", "CONTAINS", "チョコレート"},
    {"ストロベリーキャンディー", "CONTAINS", "砂糖"},
    {"ストロベリーキャンディー", "CONTAINS", "イチゴ"}
  ]
  |> Enum.reduce(graph, fn {src_name, relation, dest_name}, acc_graph ->
    {:ok, graph} = 
      Graph.add_edge(
        acc_graph,
        Edge.new(%{
          src_node: Map.get(nodes, src_name),
          dest_node: Map.get(nodes, dest_name),
          relation: relation
        })
      )
  
    graph
  end)

Commit

{:ok, commit_result} = RedisGraph.commit(conn, graph)

Query

{:ok, query_result} = RedisGraph.query(conn, graph.name, """
MATCH (n:Sweet)-[r:CONTAINS]->(m {name: "イチゴ"})
RETURN n.name AS name, n.price AS price
""")

query_result
QueryResult.results_to_maps(query_result)
query_result
|> QueryResult.pretty_print()
|> Kino.Text.new(terminal: true)
query_result
|> QueryResult.results_to_maps()
|> Kino.DataTable.new()
# 乳製品不使用のお菓子
{:ok, query_result} = RedisGraph.query(conn, graph.name, """
MATCH (s:Sweet)
WHERE NOT (s)-[:CONTAINS]->(:Ingredient {type: "乳製品"})
RETURN s.name AS name
""")

query_result
|> QueryResult.results_to_maps()
|> Kino.DataTable.new()

Delete all data

RedisGraph.query(conn, graph.name, "MATCH (n) DETACH DELETE n")