GraphGists

“自描述” Neo4j 图数据库(第 1 部分)

# FactMiners 社会游戏生态系统中的 SmartData 元模型子图设计 - 第 1 部分(共 2 部分)

作者:Jim Salmons
FactMiners.org 和 The Softalk Apple Project

日期:2014 年 1 月 25 日
版本:0.2

本 GraphGist 分为两部分,探讨了在 Neo4j 图数据库应用程序中使用的“元模型子图”设计模式

第 1 部分 本 #GraphGist 简介介绍了 元模型子图 设计及其工作原理。

第 2 部分 在我们介绍性想法的基础上,我们将开始构建 FactMiners Fact Cloud 的元模型(一个“自描述” Neo4j 数据库),该模型将捕捉到 《Softalk 杂志》48 个月刊(1980-84 年) 中锁定的丰富科技史。用例场景是一个 FactMiners 玩家,他是 The Softalk Apple Project 的代理人。此玩家(具有 Fact Cloud 所有者/创建者权限 - 请参见第 4 部分)使用 FactMiners Fact Cloud 向导设置 Softalk 杂志 Fact Cloud – 也就是说,使用向导创建和维护 Fact Cloud 的元模型子图 – 使 FactMiners 社会游戏玩家可以帮助构建 Fact Cloud,从而解锁项目在线数字档案中的数据。

第 3 部分 我们将逐步介绍一个两玩家 FactMiners 游戏场景,其中“游戏场地”是一页 Softalk 页面,上面列出了前 30 名畅销书。其中一位玩家在某轮事实挖掘中“占领”了该列表的区域。Cypher 查询片段展示了元模型子图如何帮助 FactMiners 玩家在 Softalk 杂志 FactMiners Fact Cloud 中查找、输入、验证和探索事实。[注意:本 GraphGist 内容已整合到我的 #MCN2014 演示文稿中,"事实存活之处:GraphGist 版本"。请观看我的 MCN 演示文稿中嵌入的视频的后半部分,了解页面分割游戏示例。]

第 4 部分 本 GraphGist 系列以介绍“META:Process”分区结束,其中介绍并演示了元模型的“我能做什么?”和“我该如何操作?”功能。[注意:此内容的具体处理尚未完成,虽然在我的 #cidocCRM 相关博客文章中有一些信息线索:https://goo.gl/dpbhPs。更多内容将陆续推出。]

第 1 部分:什么是“自描述” Neo4j 图数据库?

模式描述 自描述 Neo4j 数据库是指包含有关该数据库中数据的元模型子图的数据库。也就是说,数据库内部还有一个图数据库(即节点和关系的断开子集),这些数据构成一个模型,告诉我们有关包含元模型的数据库中实际数据的很多信息。典型用途 交互式应用程序,其中需要使用图数据库来灵活地但在捕获和表示稀疏、松散耦合但语义丰富的资讯空间时保持纪律性(例如,复杂杂志结构中的编辑和广告事实,例如《Softalk》的 48 个月刊)。MetaDATA 或 MetaMODEL? 模式描述中提到了“有关数据的 数据”。听起来像是元数据。是什么让这种模式成为 元模型 而不是 元数据 呢?正如本 GraphGist 系列将展示的那样,建议的 元模型子图 实际上是一个丰富描述性的模型,即元模型,它描述了数据库中数据的结构以及有关访问和工作流的过程信息,以便元模型感知的瘦客户端工具(在本例中为游戏)可以灵活地调整以代表“自描述”数据库提供编辑、可视化和其他访问服务。

adeb1e9a 5704 4bce 974a 0ade3a0dc19d 1iwZzrM6S

让我们看看最简单的例子 - 两个节点通过关系连接,以及描述它的元模型结构。

新闻界有一句老话,狗咬人不算什么大新闻,但人咬狗就是新闻。”。我们将以此格言作为我们入门示例的基础。

我们从向一个空的、迄今为止非自描述的 Neo4j 数据库添加一些“新闻”开始

CREATE (:MAN {name: "Joe"}) - [:BITES] -> (:DOG {name: "Fido"})

一个名叫 Joe 的人(我们的记者为此新闻跑遍了大街小巷)咬了一条名叫 Fido 的狗……晚上十一点的新闻!

为了使此数据库成为自描述的,我们在数据库中添加了几个节点和关系,这些节点和关系是数据库内的一个特殊用途的、不连接的子图。要创建元模型子图,我们只需在元模型中所需的任何节点上添加META标签。此 Cypher 查询创建了元模型元素,这些元素根据我们的老式新闻格言描述了咬人新闻的(必要/允许)结构

CREATE
	(man:META:Nodes {type: "MAN", name: "MAN"}),
	(dog:META:Nodes {type: "DOG", name: "DOG"}),
	news = (man - [:FROM_NODE] ->
		(:META:Relationships {type: "BITES", name: "BITES"})
		- [:TO_NODE] -> dog)
当前版本的内置 GraphGist 图可视化使用节点颜色来反映基于标签的集合成员资格。随着时间的推移,以及不断产生的“痒”需要挠,我相信我们将拥有更多 GraphGist 输出组成和样式选项。GraphGisting 作为一种探索性设计和通信媒介,实在是太棒了,以至于它会随着使用而不断改进。当 GraphGist 作者/开发者能够动态生成有用的可视化效果(如下所示)时,将非常棒,这些可视化效果将基于标签的集合成员资格显示为区域包含。
7aeaa4bf 032e 4cd4 8f36 a8543fe7a6e5 P GS2vV m

注意,数据库中的BITES关系是如何由元模型中的BITES节点建模的。这种转换映射使我们能够明确描述关系的FROM_NODETO_NODE特性,这些特性在现在是自描述的 Neo4j 数据库的非元数据中发现或允许。这个关于关系的节点实际上是它自身在元模型中关于BITES关系的微型模型的,正如将在数据库的非元数据中表达的那样。

上面的 Cypher 查询中反映了一些额外的元模型结构提示,它们协同工作以进一步描述咬人新闻数据库中数据的模型

  • 元模型中有两个带标签的子集:节点关系。结构化子集标签对于元模型子图探索的语义至关重要。

  • META:Nodes 子集中的节点具有type属性。这意味着您将在非元数据中找到标签等于该类型属性值的节点。例如,元模型中的 (:META:Nodes {type: "MAN"}) 告诉我们非元数据中将存在 (:MAN) 标签的节点。

  • 类似的映射适用于 META:Relationships 中的节点,其中元模型节点中的type属性对应于非元数据中关系的:RELTYPE标签。

这个入门示例有意地非常简单。它无法揭示**元模型子图**设计模式的全部潜力,也不能反映应用该模式时的实际复杂性。在本系列 GraphGist 的第二部分中,我们将开始构建 FactMiners Fact Cloud 的元模型,该元模型是 Softalk Magazine 在线数字档案的补充。除了详细说明元模型的结构外,我们还将涉及处理节点和关系属性等实际复杂性。

但首先,所以呢?有了元模型,我现在能做些什么呢?

自描述:谁在听?为什么听?

术语“自描述”Neo4j 数据库意味着有人或某物正在“倾听”并理解该描述。这个“倾听者”通常是一个瘦客户端应用程序,它通过插件架构动态配置,以提供编辑、报告、可视化或其他访问服务。这些瘦客户端利用其元模型感知能力来配置编辑器,从而防止将“错误数据”输入数据库。或者,对于现有非结构化数据,此类工具可以提供“智能助手”服务,通过交互式会话来整理和增加数据的价值,从而创建和扩展有关数据的**元模型子图**。以下是一个非常基础的示例,说明了它将如何工作…

我们负责 (人)--(狗) 线索的记者建立了一个咬人新闻提示热线,以匿名接收有关城镇周围可疑咬人事件的报告。人们填写一个网络表单,提供他们所知道的有关事件的所有信息。我们将处理三个通过提示热线收到的提示,然后是一个 Cypher 查询,提示热线元模型感知瘦客户端应用程序可能会使用该查询来查找和验证有新闻价值的咬人事件

// Create a tips to be tested...
//
	// Tip 1: "Joe bites Fido." (Case: Known incident already in data)
MATCH (joe:MAN {name: "Joe"}) - [known_bite:BITES] -> (fido:DOG {name: "Fido"})
SET known_bite.status = "unconfirmed"
	// Tip 2: "Fido bites Joe." (Case: Known actors, role mismatch)
MERGE fido - [:BITES {status: "unconfirmed"}] -> joe
	// Tip 3: "Johnny bites Rover." (Case: Unknown actors, fact check assist)
CREATE (:UNK {name: "Johnny"}) - [:BITES {status: "unconfirmed"}] -> (:UNK {name: "Rover"})
WITH known_bite

// Let's see how our metamodel can help us figure out about the newsworthiness
// of these biting incident tips.
//
// First, let's find out what we know about biting incidents...
MATCH (biter) --> (bites:META:Relationships {type: "BITES"}) --> (bitee)
WITH biter, bites, bitee

// Now, round up our unconfirmed tips of bite incidents and investigate their newsworthiness...
MATCH (accused_biter) - [incident:BITES {status: "unconfirmed"}] -> (alleged_victim)
WITH biter, bites, bitee, accused_biter, incident, alleged_victim,
	accused_biter.name + " " + lower(type(incident)) + " " + alleged_victim.name + "." as unconfirmed_tip,
	// First, fact-check the accused Biter...
	CASE
	    WHEN "UNK" IN labels(accused_biter)
		THEN "Biter: FACT CHECK - Need to confirm " + accused_biter.name + " is a " + biter.type + ". Otherwise, no news."
		// We have a potentially newsworthy biter...
	    WHEN biter.type IN labels(accused_biter)
		THEN "Biter: CONFIRMED - " + accused_biter.name + " is a " + biter.type + "."
		// The known Biter is of the wrong type, no news...
		WHEN NOT (biter.type IN labels(accused_biter))
		THEN "Biter: NO NEWS - " + accused_biter.name + " is NOT a " + biter.type + "."
		// Unhandled case - The metamodel might need refining...
		ELSE "Biter: ALERT - I am confused about " + accused_biter.name + "'s role in this biting incident. A report is being logged to the Metamodel Police. Nothing to see here. Step away from the program. This just became a crime scene..."
		END as biter_assessment,
	// Next, check the alleged victim...
	CASE
	    WHEN "UNK" IN labels(alleged_victim)
		THEN "Victim: FACT CHECK - Need to confirm " + alleged_victim.name + " is a " + bitee.type + ". Otherwise, no news."
		// We have a potentially newsworthy alleged_victim...
	    WHEN biter.type IN labels(accused_biter) AND bitee.type IN labels(alleged_victim)
		THEN "Victim: CONFIRMED - " + alleged_victim.name + " is a " + bitee.type + ".<br>CONGRATULATIONS! We have NEWS! :-)"
		// If both actors are appropriate, we have a newsworthy tip! :-)
	    WHEN bitee.type IN labels(alleged_victim)
		THEN "Victim: CONFIRMED - " + alleged_victim.name + " is a " + bitee.type + "."
		// The known alleged_victim is of the wrong type, no news...
		WHEN NOT (bitee.type IN labels(alleged_victim))
		THEN "Victim: NO NEWS - " + alleged_victim.name + " is NOT a " + bitee.type + "."
		// Unhandled case - The metamodel might need refining...
		ELSE "Victim: ALERT - I am confused about " + alleged_victim.name + "'s role in this biting incident. A report is being logged to the Metamodel Police. Nothing to see here. Step away from the program. This just became a crime scene..."
		END as bitee_assessment

RETURN unconfirmed_tip as `Tip`, biter_assessment + " <br> " + bitee_assessment as `Tip Assessment Results`

经过一番调查,我们的记者确认了不完整的“Johnny 咬了 Rover”提示中物种。当记者输入这些更新后的信息时,元模型感知瘦客户端重新应用其“咬人新闻”事实检查过程,并确认我们有一个突发咬人新闻。

就是这样。想一想,这并不差。我们在数据库中添加了三个节点和两个关系,使其(至少)自描述。因为我们以与数据库中其他数据不同的方式思考数据库中的这些数据位,所以我们能够执行咬人新闻提示热线所需的“事实检查”(数据整理)任务。

但所以呢?这个小元模型可能帮助我们完成了事实检查任务,但我仍然在执行实际事实检查计算的 Cypher 代码中看到很多领域特定的知识。没错,但这是由于“编码者上下文”。为了这个入门示例的目的,我以类似“讲故事”的认知过程编写了这些查询,这些过程帮助我编写代码,就像“咬人新闻提示热线”上下文帮助您阅读和理解我的代码一样。

关键在于,这种“可读性上下文”是表面的。从根本上说,这个提示事实检查过程可以轻松地由在元模型感知客户端的通用上下文中编写的代码完成。换句话说,这个

MATCH (accused_biter) - [incident:BITES] -> (alleged_victim)
RETURN *

可以轻松地以通用上下文编写,例如 RDF 三元组

// RDF-like 'fact' context
MATCH (subject) - [verb:PREDICATE] -> (object)
RETURN *

或者您可以用任意数量的替代词汇表/上下文重新编写。但令人兴奋的是,一旦我们在元模型感知瘦客户端的插件库中拥有一个良好的通用元模型处理算法核心,我们就可以大幅减少编写领域特定代码的需求。使用 FactMiners Fact Cloud 向导等元模型构建工具,几乎所有领域特定知识都将转移到元模型中,而不是锁定在特定实例的源代码中。

这将我们带入了意外的良好结果领域,这些结果可能是构建 FactMiners 生态系统带来的有趣结果。我相信,探索 FactMiners 的“大想法”将在游戏领域之外找到广泛的应用。

进入第二部分…

这里简要探讨的想法是构建 Softalk Magazine Fact Cloud 元模型的第一步的基础,详见 本系列 GraphGist 的第二部分