BusinessDesk Kimdir?
BusinessDesk, 2008 yılından bu yana Yeni Zelanda siyasi ekonomisini ve listelenmiş ve listelenmemiş işletmelerinin durumunu ele almaktadır.
BusinessDesk'in binlerce bireysel abonesi ve 150'den fazla kurumsal ve hükümet abonesi bulunmaktadır.
Daha fazla bilgi için https://nextdeveloper.com/casestudy/businessdesk
Kamu Sektörü Vaka Çalışması
Devletle ortaklaşa yaptıkları bir projede, açıldığı günden bu yana biriktirdikleri bilgiyle binlerce haber bağlantısı aracılığıyla insanları, şirketleri ve hatta bakanlıkları birbirine bağlamak istediler ve bu konuda nasıl harekete geçebileceğimizi incelemeye başladık.
Buradaki ana amaç, bir kişinin nerede ve kiminle çalıştığını görmek ve iş yeri ilişkileri dışında kimlerle temas halinde olduğunu haberler aracılığıyla görmektir.
Problem
Buradaki ana problem, ilişkilerin nasıl olacağı, bu verilerin nerede ve nasıl saklanacağı ve bu bilginin binlerce haberde nasıl oluşturulacağı konularını netleştirmekti.
Binlerce haber, yüzlerce insan ve bu kadar çok şirketle ne yapabileceğimizi düşünmeye başladık.
İlk bakışta, projede kullandığımız MySql veritabanı ile bunu kolayca çözebileceğimiz görünüyordu. Şirket bağlantılarını insanlardan ve oradan diğer insanlardan eşleştiriyoruz. Tamam burada, peki ya haberler? Burada, sıradan bir arama işleminin bizi kurtarmayacağı, kurtarsa bile 2. seviyeden sonra ilişkilerde performans sorunları yaratacağı için ayrı bir yapıda ilerlememiz gerektiği yönünde sesler yükseldi.
Çözüm
Öncelikle, bu kişilerin ve şirketlerin ilişkilerinin nasıl olacağı kısmını çözmek gerekiyordu. Burada, ilk amacımız insanların birbirleriyle ve çalıştıkları şirketlerle olan iş ilişkilerini bulmaktı.
Sahip olduğumuz bilgilerle, insanların aktif olarak çalıştıkları ve daha önce çalıştıkları yerlere ulaşabildik. Bu, bizim için ilk ve en kolay bağlantıydı. Bunu doğrudan ulaşabileceğimiz bir seviye 1 bağlantısı olarak cebimize koyduk.
Tüm kullanıcıların bilgisini aynı mantıkla oluşturduktan sonra, tüm şirketlerin orada çalışan insanlarla olan bağlantısını da kurduk.
Bu 1. seviye ilişkilerden sonra, biraz daha detaya inip kişinin çalıştığı şirket üzerinden meslektaşlarını bulma zamanı geldi.
Burada MySql bizim için yeterli olmayacağından, Neo4j - graph database ile devam etmeye karar verdik. Neo4j'nin bu ve benzeri işler için oluşturulduğundan ve üretilen verilerin kullanımı ve gösterimi sırasında sağladığı kolaylıklardan emin olduktan sonra burada bir adım atmaya başladık.
Öncelikle, burada tüm insanları “People”, şirketleri “Entity” ve haberleri “Story” düğümleri ile oluşturduk.
Tüm bu düğümler, birbirleriyle ilişkilendirebileceğimiz bilgileri gerektiriyordu.
“People” düğümü için, aktif olarak ve geçmişte çalıştığı şirketleri “EntityIds” adlı bir diziye atadık. Bu ilişki ile aslında 1. seviye bağlantılarımızı tamamladık.
İlk bağlantılarımızı oluşturup Neo4j'ye bıraktıktan sonra, biraz daha karmaşık olan haberlere geçme zamanı geldi. Burada, haberlerdeki kişi ve şirket isimlerini bir bütün metin olarak aradık ve hangi kişi ve şirket isminin hangi haberde geçtiğini bulduk.
“Story” düğümünde “PeopleIds” ve “EntityIds” adında 2 dizi oluşturduk ve haberle bağlantılı bulduğumuz bilgileri atadık.
Daha teknik kısımları öğrenmek istiyorsanız, buradan devam edebilirsiniz.
Sonuç
Neo4j'ye tekrar döndüğümüzde, insanlar, şirketler ve haberler için düğümlerimiz ve ilgili ilişkilerimiz hazırdı.
İlk “People” düğümündeki “EntityIds” sayesinde, aşağıdaki ilişkilere doğrudan bağlantımız var.
- İnsanlar ve çalıştıkları tüm şirketler
- Şirketler ve burada çalışan tüm insanlar
Şu ana kadar hep böyle seviye 1 ilişkilerden bahsettim. İlk seviye 2 bağlantımıza meslektaşlık yoluyla erişiyoruz.
Yani; Öncelikle bir kişinin çalıştığı şirkete ulaşıyoruz, ardından bu şirketteki çalışanlara ve ilk 2. seviye bağlantımıza ulaşıyoruz.
Aynı mantıkla, meslektaşın çalıştığı diğer yerler üzerinden Neo4j aracılığıyla 3. ve 4. seviye bağlantılarımıza kolayca erişebiliriz.
Haberler için yine iş arkadaşlığı mantığıyla, “PeopleIds” ve “EntityIds” serilerindeki bilgileri kullanarak, buradaki tüm kişi ve şirketlerin 2. seviye bağlantılarını ilk olarak kurduk.
İş arkadaşlığına benzer bir mantıkla, daha önce kurduğumuz 2. seviye bağlantılar aracılığıyla bu ilişkiyi kurduğumuz kişi veya şirketlerle derinlemesine bir ilişki kurabildik.
Dikkat Edilmesi Gereken Bazı Şeyler
-
Burada, ilk ilişkiden sonra, yeni haber, kişi veya şirket değişikliği durumunda sistemin düzgün bir şekilde devam edebilmesi için, her yeni kayıt için bu sistemi tetikleyecek bir iş yaptık, böylece yalnızca değişen veriler işlenir.
-
Neo4j'de performans sorunları yaşamamak veya sonsuz bir döngüye düşmemek için verilerin doğruluğunu kontrol ettik. Ve Neo4j'deki ilişkiler için en uygun ve optimize edilmiş sorguları yazdık.
-
Projemiz ve Neo4j içinde, web sitesinde göstereceğimiz bilgileri olabildiğince basit tuttuk. Sonrasında, izleyicinin kodlar arasında boğulmadan rahatça sonuca ulaşabilmesi için gerekli yazılım ilkelerini takip ederek doğru bir kodlama ile sonuca ulaştık.
Neo4j'yi Nasıl Kullanıyoruz, Daha Fazla Teknik Bilgi
Sistemimizde people, entities, ministers ve stories olmak üzere dört farklı model bulunmaktadır. Bu modellerin tümü yönetim panelinden eklenebilir ve güncellenebilir. Model düğümleri arasındaki bağlantıları toplamak için kullanılan özel türde ilişkiler (kenarlar) de vardır.
Öncelikle, bir hikaye diğer hikaye türleri hariç her tür modelle ilişkilendirilebilir. Eğer bir hikayenin içeriği (gövde metni) bir kişi, varlık veya bakan ismini içeriyorsa, hikaye bu modelle bağlantı kurar. Bu özel bağlantı türüne REL_STORY denir.
Aşağıdaki resimde görüldüğü gibi, 24553 id numaralı hikayenin 3 bağlantısı vardır. Varlıkları kırmızı düğümlerle ve insanları mavi düğümlerle temsil ediyoruz. Dolayısıyla, id numarası 25 olan kişinin bu hikaye aracılığıyla iki diğer varlıkla bağlantılı olduğunu söyleyebiliriz.

Varlıklar, insanların şu anda çalıştıkları veya geçmişte çalıştıkları şirketlerdir. İkinci tür ilişki için bu iş ilişkisine REL_EMPLOYMENT denir. Bu tür ilişki sadece insanlar ve varlıklar arasında var olabilir.
Neo4j Servisi
Ana web uygulamamız bir MySQL veritabanı kullanıyor ve Neo4j sunucumuzdan farklı bir sunucuda bulunuyor. Bu nedenle, Neo4j sunucumuzda Laravel ile başka bir proje uyguladık. Bu yeni uygulama, ana web uygulamamızdan gelen istekleri kabul eder ve Neo4j'ye yönlendirir. Neo4j'den sonuçları aldıktan sonra, bu sonucu ana web uygulamamıza gönderir.
Ana uygulama, düğüm türü ve id'si ile bağlı düğüm id numaraları ve türlerini içeren bir HTTP isteği gönderir. Neo4j Laravel uygulaması, ana uygulamadan alınan verileri kullanarak düğümün ilişkilerini yeniler. Neo4j, verilerin MySQL sunucusunda orijinal olarak depolandığı id'leri bilir.
İşte id'leri 1, 2 ve 3 olan kişileri id'si 1 olan hikayeyle bağlayan örnek HTTP istek gövdemiz. Ayrıca ilişkinin türü belirtilmelidir.
{
“nodeClass”: “Story”,
“relatedNodeClass”: “People”,
“nodeID”: 1,
“relatedNodeIDs”: [1,2,3],
“relationType”: “REL_STORY”
}
Gözlemci Fonksiyonlar & İşler
Neo4j verilerini gözlemci sınıflar ve işler ile senkronize ediyoruz. Bu modellerde bir şey değiştiğinde, Neo4j sunucusunu güncellemeliyiz. MySQL araması bir web sayfası yüklemesi için çok fazla zaman aldığından bazı işlemler için iş kullanmamız gerekiyor. Gözlemciler görevleriyle birlikte aşağıda listelenmiştir;
Hikaye gözlemcisi: Yeni bir hikaye eklendiğinde veya hikayenin gövdesi değiştirildiğinde, o hikayenin gövdesinde kişi, varlık ve bakan isimlerini aramak için bir MySQL arama işi oluşturun. Arama sonucu elde edildikten sonra, Neo4j'ye gönderin.
Kişi gözlemcisi: Yeni bir kişi eklendiğinde veya kişinin adı değiştirildiğinde, o kişinin adını aramak için hikaye gövdelerinde bir MySQL arama işi oluşturun. Arama sonucu elde edildikten sonra, Neo4j'ye gönderin. Eğer kişinin iş geçmişi değişirse, MySQL'den tüm iş geçmişini alın ve Neo4j'ye gönderin. Ayrıca, kişinin organizasyonu da iş geçmişine eklenir.
Varlık gözlemcisi: Yeni bir varlık eklendiğinde veya varlığın adı değiştirildiğinde, o kişinin adını aramak için hikaye gövdelerinde bir MySQL arama işi oluşturun. Arama sonucu elde edildikten sonra, Neo4j'ye gönderin.
Bakan gözlemcisi: Yeni bir varlık eklendiğinde veya varlığın adı değiştirildiğinde, o kişinin adını aramak için hikaye gövdelerinde bir MySQL arama işi oluşturun. Arama sonucu elde edildikten sonra, Neo4j'ye gönderin.
Cypher Sorguları
Tüm ilişki verileri Neo4j'de depolandıktan sonra, match sorgularını kullanarak bağlantıları elde edebiliriz. Bu match sorguları, SQL'deki select sorguları gibi çalışır. Bu fonksiyonlar aşağıda listelenmiş ve açıklanmıştır;
getConnectedThroughStories()
Bu fonksiyon, giriş olarak person id, entity id veya minister id alır ve bu giriş modeline hikayeler aracılığıyla bağlı olan diğer tüm insanlar, varlıklar ve bakanları döndürür. Bu bağlantının amacı, aynı hikayelerde bahsedilen bireyleri bulmaktır. Örneğin, aşağıdaki sorgu, id'si 25 olan kişiyle hikayeler aracılığıyla bağlantılı olan tüm varlıkları alır. Bu sorgu ile herhangi bir kombinasyon yapabiliriz. Örneğin, belirli bir varlığa bağlı tüm bakanları da seçebiliriz.
MATCH (n:People)-[r1:REL_STORY]-(s:Story)-[r2:REL_STORY]-(m:Entity)
WHERE n.source_id = 25
RETURN DISTINCT m
getConnectedThroughEmployment()
Bu fonksiyon, giriş olarak person id alır ve bu giriş kişisine entities aracılığıyla bağlı olan diğer tüm insanları döndürür. Bu bağlantının amacı, ortak iş geçmişine sahip insanları bulmaktır. Örneğin, aşağıdaki sorgu, iş geçmişiyle verilen kişiye bağlı olan diğer tüm insanları alır.
MATCH (n:People)-[r1:REL_EMPLOYMENT]-(s:Entity)-[r2:REL_EMPLOYMENT]-(m:People)
WHERE n.source_id = 25
RETURN DISTINCT m
getConnectedEmployers()
Bu fonksiyon, giriş olarak person id alır ve doğrudan bağlı olan tüm entities döndürür. Bu bağlantının amacı, kişinin geçmişte ilişkili olduğu işverenleri bulmaktır. Örneğin, aşağıdaki sorgu, verilen kişinin şu anda çalıştığı ve daha önce çalıştığı tüm varlıkları alır.
MATCH (n:People)-[r:REL_EMPLOYMENT]-(m:Entity)
WHERE n.source_id = 25
RETURN DISTINCT m
getConnectedEmployees()
Bu fonksiyon, giriş olarak entity id alır ve doğrudan bağlı olan tüm people döndürür. Bu bağlantının amacı, varlığın geçmişte ilişkili olduğu çalışanları (insanları) bulmaktır. Örneğin, aşağıdaki sorgu, verilen varlığın şu anda çalıştırdığı ve daha önce çalıştırdığı tüm insanları alır.
MATCH (n:Entity)-[r:REL_EMPLOYMENT]-(m:People)
WHERE n.source_id = 12
RETURN DISTINCT m




