Tuesday 5 July 2022

Graphs are everywhere - also in Religious Texts - part 5 - Exploring the Hadith Narrator Graph

Before we can start that exploration, we do need to put in place a few additional indexes that have not yet been created in the import process: on the english translations of the hadiths, and on the scholar names. That's simple operation:

CREATE TEXT INDEX hadith_text_en FOR (h:Hadith) ON (h.text_en);
CREATE TEXT INDEX scholar_name FOR (s:Scholar) ON (s.name);

Note that these indexes are not full text indexes - but they are more optimised for text fields.

The model now looks like this: 

So now we can start some querying. This query gives us a flavour of what we could find:

MATCH (:Scholar)--(n:Hadith)--(:Source)

This is what that looks like:

Now let's look at some very specific network members. We'll start with a very well known scholar, Isma'il bin Ja'far.

Zooming into the Narration network for Isma'il bin Ja'far

Here's how we do that, at a very limited depth:

MATCH path = (s:Scholar)-[:NARRATED]->(h:Hadith)<-[:NARRATED]-(s2:Scholar)
    WHERE s.name starts WITH "Isma'il bin Ja'far" 
RETURN path;

We can of course also look at the Hadith chains that this particular scholar has been part of.

This is now also very simple:

MATCH (s:Scholar)-[hc1:HADITH_CHAIN]->(s2:Scholar)
    WHERE s.name starts WITH "Isma'il bin Ja'far" 
WITH s,hc1,s2,collect(hc1.hadith_id) as hadiths
MATCH path = (s2)-[hc2:HADITH_CHAIN*..15]->(:Scholar)
    WHERE all(r in hc2 WHERE r.hadith_id in hadiths)
    RETURN s,hc1, path

And similarly, we can also look at the aggregated hadith chains for this particular narrator:

MATCH path = (s:Scholar)-[ahc:AGGREGATED_HADITH_CHAIN*..5]->(s2:Scholar)
WHERE s.name starts WITH "Isma'il bin Ja'far" 
    and all(hc in ahc WHERE hc.nr_of_hadiths>10)
    RETURN path;

In this Neo4j Browser visualisation that looks like this: 

But if you apply a Neo4j Bloom perspective, have rule based styling on the relationhip (which will make the relationship thicker if the nr_of_hadiths property is higher), and also apply a filter to weed out the relationships with a nr_of_hadiths property lower than 10, then it looks like this:

As a final exploration step, I decided to take a look at some interesting topical Hadiths - by searching the (:Hadith) nodes' text_en property - containing the English translation of the Hadith's specific text in arabic. Since I don't speak a word of Arabic, search the English translation for keywords would be the only way to get a sense for the topical information... And of course, for me, that meant that I would want to take a look at the Hadith chains with regards to alcohol. Let's see what that would look like.

Here's a very nice and clean example:

MATCH path = (h:Hadith)--(s:Scholar)-[hc:HADITH_CHAIN*..10]-(:Scholar)
WHERE h.text_en contains "alcohol"
    AND ALL(r IN hc WHERE r.hadith_id = h.hadith_id)

And similar to the enhanced styling that we did above for the aggregated counts of hadiths on the relationship between Scholars, we can als make use of Bloom in a cool way by parametrising the topic upon which we search. All we need to do is define it in Bloom's search phrases, and introduce the $param value where we would before define "alcohol".

MATCH path = (h:Hadith)--(s:Scholar)-[hc:HADITH_CHAIN*..10]-(:Scholar)
WHERE h.text_en contains $param
    AND ALL(r IN hc WHERE r.hadith_id = h.hadith_id)

So this is giving us a really nice view on these networks - tons of further investigation and exploration is of course possible. But I thought I would take it to another level, and do some playing around with the Neo4j Graph Data Science library.

Looking forward already!


PS: as always all the code/queries are available on github!

PPS: you can find all the parts in this blogpost on the following links

No comments:

Post a Comment