是否可以创建图形数据库来模拟产品功能(手机),并从该模型生成所有有效的手机组合?。
我已经创建了这样的数据库。
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
。
最终目的是检查是否可以在图形DB中存储/计算特征模型。
我是Neo4j的新手,正在研究模拟行为的可能方法,否则使用标记过渡系统建模。
答案 0 :(得分:2)
我意识到您询问了Neo4j解决方案,但我想为您提供另一种型号。正如你所说的那样,这听起来像是你处于分析阶段。因此,您可能不需要数据库。
此域的模型的一种方法是作为"特征流"顶点代表"产品问题"并且有向边代表X" has-feature"收率
从源节点和汇聚节点phone
和product
开始。
如果关注点X需要另一个关注点Y,则从X到Y将存在单个边缘。这实际上使得关注Y"强制性"。如果有一个选项,则从X到Y和Z将有多个传出边。网络流中的最终关注点链接到product
汇聚节点。所有产品功能的组合成为从源到接收器的所有路径的集合。
以下是Clojure中的示例实现。
有向无环图是一个散列图,顶点为键,顶点向量为值:
(def g
{:phone [:mobilephone]
:mobilephone [:screen]
:screen [:camera :product]
:camera [:highrescam :lowrescam]
:highrescam [:flash]
:lowrescam [:flash]
:flash [:product]})
当您在此网络中从左向右移动时,您将按功能构建产品功能。
我们可以使用从源到接收器的深度优先搜索找到所有路径:
(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会提供allPaths
algorithm。
答案 1 :(得分:1)
你想要做的是一个坏主意,因为你不能对Neo4j"嘿,我希望每个Phone节点只与Camera节点有一个关系,并且总是有一个Screen,和...." Neo4j中存在约束,但你不能限制这样的事情。
Neo4j是一个数据库,正如每个数据库应该做的那样,它用于存储和使用数据,而不是像你想要的那样创建数据(使用约束创建电话和组件的每个组合)。
这种逻辑应该在你的应用程序中实现,然后使用一个好的数据模型存储在数据库中(我提供的那个似乎 - 不是最好的但是很好)
像你一样创建节点是没用的,因为你只是创建没有标签,没有属性的空节点。此外,标签可以帮助您确保良好的性能。
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)
要匹配您的有效手机,您可以这样做:
产品1(只有一个强制项目的手机):
Match (phone:Phone)-[:MANDATORY]->(sc:Component)
WHERE count(sc) = 1
return phone
产品2(电话)
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: "Stackoverflow"})
(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)
然后,您可以使用新的手机节点创建有效组合:
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.
但正如你所看到的,你必须用你的手和一堆请求来创造每一个组合,有点痛苦。