我有一个存储在neo4j中的严重关联的数据模型。数据如下:
Component -> Part (only 1)
\-> Fastener (only 1)
随后,任何带有标签Part或Fastener的节点都可以有任意数量的链接到其他节点(但永远不会回到组件)。
我要做的是返回所有组件的Part列,Fastener列,以及该Part的连接的一列(比如一个字典数组)以及该Fastener连接的一列。
目前我有一个非常基本的查询“工作”但产生同一组件的多行,其中一行包含唯一的零件或紧固件连接。查询是:
MATCH (c:Component)-[:MADE_WITH]->(p:Part), (c)-[:MADE_WITH]->(f:Fastener), (p)-[p_m:MATERIAL]->(p_m_unk), (f)-[f_m:MATERIAL]->(f_m_unk)
RETURN c.name, p, f, p_m_unk, p_m, f_m_unk, f_m
经过一些阅读后,似乎COLLECT功能将完成我需要的部分功能,但如果我这样做:
MATCH (c:Component)-[:MADE_WITH]->(p:Part), (c)-[:MADE_WITH]->(f:Fastener), (p)-[p_m:MATERIAL]->(p_m_unk), (f)-[f_m:MATERIAL]->(f_m_unk)
RETURN c.name, p, f, COLLECT([p_m_unk, p_m]), COLLECT([f_m_unk, f_m])
由于具有较少数据的列(p_m_unk
或f_m_unk
)将具有重复的行,因此这并不是我想要的。
如何让此查询为包含所有部件c.name
,紧固件p
以及所有各自的第一级连接的每个f
返回一行?
(我已经将标签的实际结构和名称更改为比我的用例更通用,但数据模型和查询仍然相同。)
答案 0 :(得分:3)
您正走在正确的轨道上,我认为问题在于您在开始时尝试进行所有匹配,即生成笛卡尔积并最终在您的收藏中创建重复项。您将要分解您的匹配项,单独收集数据(因此每个步骤的输出是每个组件的一行)以避免使用笛卡尔积。
// you can still match against part and fastener together to start
MATCH (c:Component)-[:MADE_WITH]->(p:Part), (c)-[:MADE_WITH]->(f:Fastener)
WITH c, p, f
// now match on part connections and collect
MATCH (p)-[:MATERIAL]->(p_m_unk)
WITH c, p, f, COLLECT(p_m_unk) as partConnections
// now match on fastener connections and collect
MATCH (f)-[:MATERIAL]->(f_m_unk)
// could do a return here if we wanted to
WITH c, p, f, partConnections, COLLECT(f_m_unk) as fastenerConnections
RETURN c.name, p, f, partConnections, fastenerConnections
答案 1 :(得分:1)
如果可以按@app.route('/active_jobs/new', methods=['POST'])
def add_job():
ajobs = mongo.db.ajobs
jobdate = request.json['jobdate']# date of job
jobtime = request.json['jobtime']# time of job
plant = request.json['plant']# plant for job
po = request.json['po']# production order
company = request.json['company']# client company name
client = request.json['client']# person in charge
jobaddress = request.json['jobaddress']#job address
use = request.json['use']# concrete use in site
m3 = request.json['m3']#job volume
formula = request.json['formula']#job formula
placement = request.json['placement']#type of placement
badmix1 = request.json['badmix1']#batch admixture add-on
badmix2 = request.json['badmix2']#batch admixture add-on
badmix3 = request.json['badmix3']#batch admixture add-on
confirmation = request.json['confirmation']#level of confirmation for job
status = request.json['status']#job status
ajob_id = ajobs.insert({
'jobdate' : jobdate, 'jobtime' : jobtime, 'plant': plant,
'po' : po, 'company' : company, 'client' : client, 'jobaddress' : jobaddress,
'use' : use, 'm3' : m3, 'formula' : formula, 'placement' : placement,
'badmix1' : badmix1, 'badmix2' : badmix2, 'badmix3' : badmix3,
'confirmation' : confirmation, 'status' : status
})
new_job = ajobs.find_one({'_id' : ajob_id})
output = ({
'jobdate' : new_job['jobdate'], 'jobtime' : new_job['jobtime'],'plant': new_job['plant'],
'po': new_job['po'], 'company': new_job['company'], 'client': new_job['client'],
'jobaddress': new_job['jobaddress'], 'm3': new_job['m3'], 'use': new_job['use'],
'formula': new_job['formula'], 'placement': new_job['placement'],
'badmix1': new_job['badmix1'], 'badmix2': new_job['badmix2'], 'badmix3': new_job['badmix3'],
'confirmation': new_job['confirmation'],'status': new_job['status']
})
return jsonify({'verify new job': output})
返回两行,Component
一行,Part
一则,则查询可以这样简单:
Fastener
该查询假定MATCH (c:Component)-[:MADE_WITH]->(pf)-[m:MATERIAL]->(unk)
RETURN c.name, LABELS(pf)[0] AS label, pf, COLLECT({m:m, unk:unk}) AS materials;
和Part
个节点没有其他标签。
以下是一个示例结果:
Fastener
但是,如果您真的是单行上每个╒══════╤════════╤═════════════╤══════════════════════════════╕
│c.name│label │pf │materials │
╞══════╪════════╪═════════════╪══════════════════════════════╡
│Froomb│Fastener│{name: Batz} │[{m: {name: MFlidget}, unk: {n│
│ │ │ │ame: Flidget}}, {m: {name: MCo│
│ │ │ │rb}, unk: {name: Corb}}] │
├──────┼────────┼─────────────┼──────────────────────────────┤
│Froomb│Part │{name: Bleet}│[{m: {name: MSignaft}, unk: {n│
│ │ │ │ame: Signaft}}, {m: {name: MTr│
│ │ │ │em}, unk: {name: Trem}}, {m: {│
│ │ │ │name: MMert}, unk: {name: Mert│
│ │ │ │}}] │
└──────┴────────┴─────────────┴──────────────────────────────┘
的结果,则此查询将执行此操作:
Component
MATCH (c:Component)-[:MADE_WITH]->(pf)-[m:MATERIAL]->(unk)
WITH c.name AS name, pf, COLLECT(m) AS ms, COLLECT(unk) AS unks
ORDER BY LABELS(pf)[0] DESC
WITH name, COLLECT({pf: pf, ms:ms, unks:unks}) AS data
RETURN name, (data[0]).pf AS p, (data[1]).pf AS f, (data[0]).ms AS p_ms, (data[0]).unks AS p_m_unks, (data[1]).ms AS f_ms, (data[1]).unks AS f_m_unks;
子句按ORDER BY
节点的标签按降序排序,以便在pf
集合中data
数据的索引为0并且Part
数据的索引为。
以下是结果的样子(使用相同的样本数据):
Fastener
答案 2 :(得分:0)
您可以在DISTINCT
函数调用中使用COLLECT
修饰符。
RETURN c.name, p, f, COLLECT(DISTINCT [p_m_unk, p_m]), COLLECT(DISTINCT [f_m_unk, f_m])
这将删除更长的列表中的重复项。