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

计算neo4j图形数据库以获得组合结果,neo4j,graph-databases,Neo4j,Graph Databases,是否可以创建一个图形数据库来模拟产品功能(电话),并从该模型生成所有有效的电话组合 我创建了一个这样的数据库 CREATE (mobilephone:Phone), (screen:Component), (camera:Component), (lowrescam:Component), (hirescam:Component), (flash:Component), (mobilephone)-[:MANDATORY]->(screen), (mobilephone)-[:OPTIO

是否可以创建一个图形数据库来模拟产品功能(电话),并从该模型生成所有有效的电话组合

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

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)
我希望能够获得给定型号的手机的所有有效组合

结果应该是:

产品1:

mobilephone,screen
产品2:

mobilephone,screen,camera,lowrescam,flash
产品3:

mobilephone,screen,camera,hirescam,flash
无效产品是:

mobilephone,screen,camera,lowrescam,hirescam,flash
这是因为该型号不允许使用
CHOOSE1
的两种相机类型

最终目的是检查特征模型是否可以存储/计算在图形数据库中

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

TL;博士 你想做的是一个坏主意,因为你不能对Neo4j说“嘿,我希望每个电话节点只有一个与摄像头节点的关系,并且总是有一个屏幕,而且……” Neo4j中存在约束,但不能约束这样的东西

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

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

始终使用标签 像您这样创建节点是无用的,因为您只是创建没有标签、没有属性的空节点。此外,标签有助于确保良好的性能

例子 编辑 要匹配您的有效手机,您可以这样做:

产品1(只有一个必填项的手机):

产品2(一部电话)

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

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

创造 询问 然后,您可以创建与新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解决方案,但我想为您提供另一个型号。正如你所说,这听起来像是在分析阶段。因此,您可能不需要数据库

该领域模型的一种方法是作为“特征流”网络,其中顶点表示“产品关注点”,定向边表示X“具有特征”Y

从源节点和接收器节点
电话
产品
开始

如果一个关注点X需要另一个关注点Y,则从X到Y将有一条边。这实际上使关注点Y成为“强制性的”。如果有一个选项,则从X到(比如)Y和Z将有多个传出边缘。网络流链接到
产品
接收器节点的最终关注点。所有产品功能的组合成为从源到接收器的所有路径的集合

下面是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])
为手机输入引入触摸屏和键盘选项非常简单:

(def g
  {:phone [:mobilephone]
   :mobilephone [:touchscreen :keyboard]
   :touchscreen [:camera :product]
   :keyboard [:camera :product]
   :camera [:highrescam :lowrescam]
   :highrescam [:flash]
   :lowrescam [:flash]
   :flash [:product]})
同样,模型中的模型:

正如预期的那样,引入新的二进制选项会使路径数增加一倍:

(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将为您提供一个完整的解决方案。

谢谢您的回答,但在这种情况下,我不会寻找路径。例如,您可以有一个模型,其中可以有两种相机类型(相同级别的组件),我有一个特征模型,从该模型可以生成跟踪树并遍历它以获得产品。
(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})))
(all-paths g :phone :product)

([:phone :mobilephone :screen :camera :highrescam :flash :product]
 [:phone :mobilephone :screen :camera :lowrescam :flash :product]
 [:phone :mobilephone :screen :product])
(def g
  {:phone [:mobilephone]
   :mobilephone [:touchscreen :keyboard]
   :touchscreen [:camera :product]
   :keyboard [:camera :product]
   :camera [:highrescam :lowrescam]
   :highrescam [:flash]
   :lowrescam [:flash]
   :flash [:product]})
(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])