オリジナルリンク:https://streamsets.com/blog/visualizing-analyzing-salesforce-data-neo4j/
グラフィックデータベースノードを介して、エッジ、およびデータストアを表現するための属性、迅速かつ容易に複雑な階層を取得できるようにすることは、従来のリレーショナル・データベースにモデル化することは困難であろう。Neo4jは広くコミュニティに展開されているオープンソースのグラフデータベースと、このブログの記事では、私が使用する方法を紹介しますStreamSetsにデータコレクタ Salesforceのケースからデータを読み取るために(SDC)を、そして使用のNeo4j JDBCドライバをグラフィックスにデータをロードしますデータベース。
Salesforceのケース
Salesforceのクラウドサービスは、サービスとして顧客サポートを提供します。コアコンセプトはこのことである場合 、チケット内の他のシステムに似て- 。ケースはありアカウント、アカウントの連絡先だけでなく、関連するいくつかの他の標準およびカスタムのSalesforceオブジェクトを。継続的なクラウドデータ分析サービスは、(のような他のデータとサービスクラウドデータにより、優れた顧客サービスを提供するための鍵である売上高の雲組み合わせる機会)、我々は、営業チームがビジネスを繰り返し助けるために顧客サポートを識別することにより、サービスチケットを提出することができます。私たちはSalesforceのから抽出し、SDCのNeo4jを書き込んを使用する方法に必要なすべての情報を見てみましょう。
Salesforceのからケースを読みます
以来、バージョン2.2.0.0を持つSDCが提供されてSalesforceの起源あなたのことができますSOQLクエリデータを読み込み、SalesforceのSOAPまたはバルクAPIを。我々は使用することができますリレーショナルクエリ SOQLケースとその関連を取得するために、単一のクエリでアカウントと連絡先を:
SELECT Id, Account.Id, Account.Name, CaseNumber,
Contact.Id, Contact.Name, Contact.Account.Id,
Contact.Account.Name, Status, Product__c,
Subject, Priority, Description, IsClosed,
OwnerId
FROM Case
WHERE Id > '${OFFSET}'
ORDER BY Id
単一のクエリでは、我々は、IDがオフセットすべてのケース与えられ、IDおよびそれに関連するアカウントの名前よりも大きい取得したアカウントの詳細ID及び念のために自分のアカウントに関連付けられている彼らの連絡先や自分の連絡先を(名前異なります))。我々はまた、あるそれに関連する製品コード、検索中のSalesforce Developer Editionのカスタムフィールドを。
ソースクエリとの間の関係のSalesforceの実装とフィールドの階層構造を持つレコードを生成します。
データが書かれているのNeo4j
私たちはのNeo4jのために、Salesforceのデータを変換する必要はありませんので、我々は非常に単純なパイプラインを構築することができますので。
Neo4jとリレーショナルデータベースので非常に異なっているので、SQLを使用していません。代わりに、我々はによってサイファーグラフィカルなデータベースと対話します。特に、我々はサイファー使用することができます MERGEのデータ「に」句を。
現在、JDBCプロデューサー先は、 ハードコーディングされたSQL INSERTを使用しています-私たちはすべてのステートメントを記述することはできません。JDBCのクエリの実行より柔軟なので、ここでそれを使用しています。彼らは大量のデータ用に最適化されていないので、パフォーマンスはあなたがSDCから期待するかもしれないものではありません-しかし、プログラムの実装は、実際にデータパスで動作するように設計されていないことに注意してください。
我们可以将执行程序配置 jdbc:neo4j:bolt://localhost
为JDBC URL以访问localhost上的Neo4j,并使用SDC的表达式语言 将查询直接放入JDBC Executor的配置中以填充该语句。这是一个非常简单的示例,如果数据库中还没有匹配的节点,则只创建一个案例节点:
MERGE (case:Case {
CaseId: "${record:value('/Id')}",
CaseNumber: "${record:value('/CaseNumber')}",
Status: "${record:value('/Status')}",
Subject: "${record:value('/Subject')}",
Priority: "${record:value('/Priority')}",
Description: "${record:value('/Description')}",
IsClosed: ${record:value('/IsClosed')}
})
虽然使用相同数据多次运行此语句只会导致数据库中的单个节点,但如果MERGE调用之间的任何属性发生更改,它仍会创建重复节点,因此最好合并唯一记录ID和SET其余属性:
MERGE (case:Case { CaseId: "${record:value('/Id')}" })
ON CREATE SET case.CaseNumber = "${record:value('/CaseNumber')}",
case.Status = "${record:value('/Status')}",
case.Subject = "${record:value('/Subject')}",
case.Priority = "${record:value('/Priority')}",
case.Description = "${record:value('/Description')}",
case.IsClosed = ${record:value('/IsClosed')}
但是,我们可以做更多的事情!由于我们有相关的帐户和联系人数据,我们可以在一个语句中使用多个MERGE子句来处理案例,帐户,联系人及其之间的关系:
// 'Create' should be read as "Create, if it does not already exist"
// in each case!
MERGE (case:Case { CaseId: "${record:value('/Id')}" })
ON CREATE SET case.CaseNumber = "${record:value('/CaseNumber')}",
case.Status = "${record:value('/Status')}",
case.Subject = "${record:value('/Subject')}",
case.Priority = "${record:value('/Priority')}",
case.Description = "${record:value('/Description')}",
case.IsClosed = ${record:value('/IsClosed')}
// Create the corresponding account
MERGE (account1:Account { AccountId:"${record:value('/Account/Id')}" })
ON CREATE SET account1.Name = "${record:value('/Account/Name')}"
// Create the corresponding contact
MERGE (contact:Contact { ContactId:"${record:value('/Contact/Id')}" })
ON CREATE SET contact.Name = "${record:value('/Contact/Name')}"
// Create the contact's account
MERGE (account2:Account { AccountId:"${record:value('/Contact/Account/Id')}" })
ON CREATE SET account2.Name = "${record:value('/Contact/Account/Name')}"
// Create the corresponding product
MERGE (product:Product { Code:"${record:value('/Product__c')}" })
// Create a relationship between the case and its account
MERGE (case)-[:associatedWith]->(account1)
// Create a relationship between the case and its contact
MERGE (case)-[:associatedWith]->(contact)
// Create a relationship between the contact and its account
MERGE (account2)-[:isParent]->(contact)
// Create a relationship between the case and its product
MERGE (case)-[:concerns]->(product)
现在应该明白为什么我们使用MERGE而不是CREATE,即使是在单次运行数据时:尽管我们在处理查询结果时只遇到一次每个案例,但我们可能会遇到任意次数的关联对象。我们不想创建一大堆重复节点!
在运行管道之前,我们可以做出的一个可选优化是告诉Neo4j Id
Salesforce对象上的字段(以及产品的代码属性)是唯一键。这告诉Neo4j创建相关索引并提高性能:
CREATE CONSTRAINT ON (c:Case) ASSERT c.CaseId IS UNIQUE;
CREATE CONSTRAINT ON (a:Account) ASSERT a.AccountId IS UNIQUE;
CREATE CONSTRAINT ON (p:Product) ASSERT p.Code IS UNIQUE;
CREATE CONSTRAINT ON (c:Contact) ASSERT c.ContactId IS UNIQUE;
使用标准样本数据针对Salesforce Developer Edition运行管道只需几秒钟,并在Neo4j的浏览器界面中实现以下可视化:
我们不仅可以与可视化,检查节点和以下关系进行交互,还可以使用Cypher查询来分析数据。例如,让我们看看所有具有“新”案例的帐户:
MATCH (c:Case)-[r:associatedWith]-(a:Account)
WHERE c.Status = "New"
RETURN c, r, a
我们还可以使用表格输出构建Cypher查询。例如,帐户名称和每个帐户的已关闭案例数量:
MATCH (c:Case)-[r:associatedWith]-(a:Account)
WHERE c.IsClosed
RETURN a.Name as accountName, COUNT(a) as numberOfCases
ORDER BY numberOfCases DESC
我们可以继续以不同的方式探索数据,例如,“谁是与特定产品打开的案例的联系人?”。
从Salesforce读Opportunity数据
SELECT Id, Account.Id, Account.Name, Amount, ExpectedRevenue,
IsClosed, Name, StageName
FROM Opportunity
WHERE Id > '${OFFSET}'
ORDER BY Id
注意 - 我们检索帐户ID和名称,以便我们可以将机会链接到图表中的现有帐户节点。
Cypher声明遵循与案例相同的模式:
MERGE (oppty:Opportunity { OpportunityId: "${record:value('/Id')}" })
ON CREATE SET oppty.Amount = ${record:value('/Amount')},
oppty.ExpectedRevenue = ${record:value('/ExpectedRevenue')},
oppty.IsClosed = ${record:value('/IsClosed')},
oppty.Name = "${record:value('/Name')}",
oppty.StageName = "${record:value('/StageName')}"
MERGE (account:Account { AccountId:"${record:value('/Account/Id')}" })
ON CREATE SET account.Name = "${record:value('/Account/Name')}"
MERGE (oppty)-[:associatedWith]->(account)
実行パイプラインは、いくつかの新しいアカウントだけでなく、チャートのチャンスを増加します - これらは潜在的な顧客やクライアントの場合に関連するものではありません。
表示例は、予想される収益機会によってソートされた、アカウントを開きます。
MATCH (c:Case)-[r1:associatedWith]->(a:Account)<-[r2:associatedWith]-(o:Opportunity)
WHERE c.Status <> "Closed"
WITH a, SUM(o.ExpectedRevenue) AS totalExpectedRevenue
ORDER BY totalExpectedRevenue DESC
RETURN a.Name, totalExpectedRevenue
共同石油・ガス会社の$ 5.5万人から。
結論
Salesforceの起源は、あなたが簡単にSalesforceのデータから、階層としてモデル化されたオブジェクトを関連フィールドを取得することができます。任意のクエリのサポート任意のJDBCデータストレージ用のJDBCキュータのサポートも、SQLデータストアを使用しますが、覚えていない人たち、それが大きなデータセット用に最適化されていません。あなたがのNeo4jのユーザーである場合は、してくださいデータコレクタStreamSetsをダウンロードする -それがオープンソースであり、それは、さまざまなデータソースから読み取ることができます。あなたは、グラフィックスデータベースにデータをロードする必要があるときは、SDCを試してみてください、コメントであなたのパフォーマンスについて教えてください!