cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Trying to create a recipes graph by importing collection from MongoDB

My goal is to connect a MongoDB database of different recipes with Neo4j and create a graph with the recipes and their corresponding ingredients.

I am using Neo4j Desktop version 1.3.4, and would like to read some documents from a collection in MongoDB. Each document would look like the following:

{"id": 0001, "title": title, "ingredients": [A,B,C]}

Can I obtain my goal with any of the functions from apoc? Because I cannot find any (I assume they exist) method that allows to pick a JSON like the one above and create some nodes and relations between this nodes using the keys and values from the JSON itself. The desired graph would look like:

(Ingredient A) <----- [has] ---- (Recipe) ---- [has] ----> (Ingredient B)

Can Neo4j achieve this somehow?

Thank you for reading.

1 ACCEPTED SOLUTION

apoc.load.json

...is probably one of the most used procedures in APOC. I'm using it a lot in my own project. Here's one of my cypher scripts combining periodic.commit with load.json, to handle large volumes of data.

Here's a short example, using a valid tweak of your json:

Source data at url: https://example.com/data/bakery.json

{
    "documents" :  [
        {"id": 1001, "title": "Cake", "ingredients": ["flour","eggs","sugar"]},
        {"id": 1002, "title": "Cookie", "ingredients": ["flour","eggs","sugar","chocolate"]}
    ]
}

Cypher

CALL apoc.load.json("https://example.com/data/bakery.json") YIELD value
UNWIND value.documents AS doc
  MERGE (d:Document {id: doc.id})
  SET d.title = doc.title

  UNWIND doc.ingredients as ingredient
    MERGE (i:Ingredient {name: ingredient})
    MERGE (d)-[:USES]->(i)

I'd advise putting ingredient quantities in the :USES relationship once you have them:

...
MERGE (d)-[u:Uses]->(i)
  SET u.unit = "cup"
  SET u.amount = "1.5"
  SET u.readable = "1 1/2 cups"
  SET u.ml = 350

Recipes come with many other complex patterns, like ordered steps, time/temp, methods. Those will get fun and interesting very quickly, if you're going to dive that deep. You could also, just as easily, stick the steps and explanation as text on the :Document node, and not worry about graphing it at all.

View solution in original post

1 REPLY 1

apoc.load.json

...is probably one of the most used procedures in APOC. I'm using it a lot in my own project. Here's one of my cypher scripts combining periodic.commit with load.json, to handle large volumes of data.

Here's a short example, using a valid tweak of your json:

Source data at url: https://example.com/data/bakery.json

{
    "documents" :  [
        {"id": 1001, "title": "Cake", "ingredients": ["flour","eggs","sugar"]},
        {"id": 1002, "title": "Cookie", "ingredients": ["flour","eggs","sugar","chocolate"]}
    ]
}

Cypher

CALL apoc.load.json("https://example.com/data/bakery.json") YIELD value
UNWIND value.documents AS doc
  MERGE (d:Document {id: doc.id})
  SET d.title = doc.title

  UNWIND doc.ingredients as ingredient
    MERGE (i:Ingredient {name: ingredient})
    MERGE (d)-[:USES]->(i)

I'd advise putting ingredient quantities in the :USES relationship once you have them:

...
MERGE (d)-[u:Uses]->(i)
  SET u.unit = "cup"
  SET u.amount = "1.5"
  SET u.readable = "1 1/2 cups"
  SET u.ml = 350

Recipes come with many other complex patterns, like ordered steps, time/temp, methods. Those will get fun and interesting very quickly, if you're going to dive that deep. You could also, just as easily, stick the steps and explanation as text on the :Document node, and not worry about graphing it at all.