计算 neo4j 图形数据库以获得组合结果

Computing a neo4j graph database to get combinatory results

是否可以创建一个图形数据库来模拟产品特性 (Phone) 并从该模型生成所有有效的 phone 组合?

我创建了一个这样的数据库。

CREATE
(mobilephone:Phone),
(screen:Component),
(camera:Component),
(lowrescam:Component),
(hirescam:Component),
(flash:Component),

(mobilephone)-[:MANDATORY]->(screen),
(mobilephone)-[:OPTIONAL]->(camera),
(camera)-[:CHOOSE1]->(lowrescam),
(camera)-[:CHOOSE1]->(hirescam),
(camera)-[:REQUIRES]->(flash)


(mobilephone)-[:MANDATORY]->(screen),
(mobilephone)-[:OPTIONAL]->(camera),
(camera)-[:CHOOSE1]->(lowrescam),
(camera)-[:CHOOSE1]->(hirescam),
(camera)-[:REQUIRES]->(flash)

我希望能够获得 phone 给定模型的所有有效组合。

结果应该是:

产品 1:

mobilephone,screen

产品 2:

mobilephone,screen,camera,lowrescam,flash

产品 3:

mobilephone,screen,camera,hirescam,flash

无效产品是:

mobilephone,screen,camera,lowrescam,hirescam,flash

这是因为模型不允许CHOOSE1的两种相机类型。

最终目的是检查特征模型是否可以 stored/computed 在图形数据库中。

我是 Neo4j 的新手,正在研究建模行为的可能方法,否则使用标记的转换系统建模。

TL;DR

你想做的是个坏主意,因为你不能对 Neo4j 说“嘿,我希望每个 Phone 节点与相机节点只有一个关系,并且总是有一个屏幕, 和....” Neo4j 中存在约束,但你不能约束这种东西。

Neo4j 是一个数据库,正如每个数据库都应该做的那样,它用于存储和使用数据,而不是像您想要的那样创建数据(使用约束创建 phone 和组件的每个组合)。

这种逻辑应该在你的应用程序中实现,然后使用一个好的数据模型存储在数据库中(我提供的那个似乎 - 不是最好的但是 - 很好)

始终使用标签

像您那样创建节点是没有用的,因为您只是在创建没有标签、没有属性的空节点。此外,标签可帮助您确保良好的性能。

例子

CREATE
(mobilephone:Phone),
(screen:Component),
(camera:Component),
(lowrescam:Component),
(hirescam:Component),
(flash:Component),

(mobilephone)-[:MANDATORY]->(screen),
(mobilephone)-[:OPTIONAL]->(camera),
(camera)-[:CHOOSE1]->(lowrescam),
(camera)-[:CHOOSE1]->(hirescam),
(camera)-[:REQUIRES]->(flash)

编辑

要匹配您的有效 phone,您可以这样做:

产品 1(phone 只有一个必填项):

Match (phone:Phone)-[:MANDATORY]->(sc:Component)
WHERE count(sc) = 1
return phone

产品 2(phone)

Match (phone:Phone)-[:MANDATORY]->(sc:Component),
(phone)-[:OPTIONAL]->(ca:Component),
(phone)-[:CHOOSE1]->(cam:Component),
(cam)-[:REQUIRES]->(f:Component)
WHERE count(cam) = 1;
RETURN phone, sc, ca, cam, f

如您所见,每个案例的请求都非常具体。我认为您可能需要重新考虑您的数据模型,因为我认为这个模型不是一个好模型。

让我向您推荐一个更好的数据模型:

创作

(phone: Phone{name: "Whosebug"})
(sc:Screen:Mandatory {name: "LCD blabla HD 1500000p")//The screen is a Screen, and it's a mandatory
(camera:Camera:Unique {name: "Camera"})//The camera must be unique
(flash:Flash{intensity: "1000"})//The flash is just... a flash
(camera)-[Requires]->(flash)

查询

然后,您可以使用新的 phones 个节点创建有效组合:

MATCH (sc:Screen:Mandatory {name: "LCD blabla HD 1500000p")
CREATE (phone:Phone {name: "Example"})-[:USES]->(sc:Screen)
RETURN phone //and here you have your first combination, a phone with just a screen.

但是如您所见,您必须亲手和一堆请求来创建每个组合,这有点痛苦。

我知道您问的是 Neo4j 解决方案,但我想为您提供另一种模型。正如您所说,这听起来像是您处于分析阶段。因此,您可能不需要数据库。

该领域模型的一种方法是 "feature flow" 网络,其中顶点表示 "product concerns",有向边表示 X "has-feature" Y.

从源节点和汇节点开始 phoneproduct

如果关注点 X 需要另一个关注点 Y,则从 X 到 Y 将只有一条边。这实际上使关注点 Y "mandatory"。如果有一个选项,将有多个从 X 到 Y 和 Z 的出边。网络中的最终关注点 link 到 product 汇节点。所有产品特征的组合成为从源到汇的所有路径的集合。

这是 Clojure 中的示例实现。

有向无环图是一个以顶点为键、以顶点向量为值的哈希图:

(def g
  {:phone [:mobilephone]
   :mobilephone [:screen]
   :screen [:camera :product]
   :camera [:highrescam :lowrescam]
   :highrescam [:flash]
   :lowrescam [:flash]
   :flash [:product]})

在 yEd 中将其可视化,我们得到:

当您在此网络中从左到右遍历时,您正在逐个功能地构建您的产品。

我们可以使用深度优先搜索从源到汇找到所有路径:

(defn all-paths [graph source sink]
  (letfn [(dfs [path visited]
            (let [vertex (peek path)]
              (if (= sink vertex) [path]
                  (->> vertex
                       graph
                       (remove visited)
                       (mapcat #(dfs (conj path %) (conj visited %)))))))]
    (dfs [source] #{source})))

:phone 作为源并以 :product 作为接收器调用,我们得到:

(all-paths g :phone :product)

([:phone :mobilephone :screen :camera :highrescam :flash :product]
 [:phone :mobilephone :screen :camera :lowrescam :flash :product]
 [:phone :mobilephone :screen :product])

为 phone 输入引入触摸屏和键盘选项很简单:

(def g
  {:phone [:mobilephone]
   :mobilephone [:touchscreen :keyboard]
   :touchscreen [:camera :product]
   :keyboard [:camera :product]
   :camera [:highrescam :lowrescam]
   :highrescam [:flash]
   :lowrescam [:flash]
   :flash [:product]})

同样,yEd 中的模型:

不出所料,引入新的二元期权使路径数量翻倍:

(all-paths g :phone :product)

([:phone :mobilephone :touchscreen :camera :highrescam :flash :product]
 [:phone :mobilephone :touchscreen :camera :lowrescam :flash :product]
 [:phone :mobilephone :touchscreen :product]
 [:phone :mobilephone :keyboard :camera :highrescam :flash :product]
 [:phone :mobilephone :keyboard :camera :lowrescam :flash :product]
 [:phone :mobilephone :keyboard :product])

如果您最终决定需要数据库,Neo4j 会提供

全部恢复。