Neo4jrb继承场景下调用子类关联关系的作用域问题咨询
问题解答
1. 属性可查询但关联方法不存在的原因
- 执行属性查询时,
where方法只会将属性条件直接拼接为Cypher的WHERE子句,Cypher本身无强Schema校验,只要节点实际存在对应属性就可以正常返回结果,不会校验属性归属的模型类。 - 关联方法(如
friends)是定义在子类Facebook上的,socials关联的代理对象绑定的基类是Social,Social类中没有定义friends关联,因此调用时会报方法不存在错误。关联方法的查找是基于代理当前绑定的模型类,不会自动扫描所有子类的关联定义。
2. 派生类关系的查询方法
你之前尝试的as_models是多模型适配方法,不符合单子类绑定的需求,以下是可用方案:
方案1:新增定向关联(最推荐,链式调用最顺畅)
直接在Person类中新增指向Facebook子类的关联,后续可直接链式调用:
class Person # 原有代码不变 has_many :out, :facebook_accounts, type: :HAS_ACCOUNT, model_class: 'Facebook', unique: true end # 调用示例 Person.as(:p).facebook_accounts.friends
方案2:查询时临时绑定子类
使用as_model方法将关联代理临时绑定到Facebook子类:
Person.as(:p).socials.as_model(Facebook).friends
注意:如果你使用的是9.0以下的旧版本activegraph gem,as_model方法名为cast_as,可替换尝试。
方案3:显式匹配关系逻辑
和原生Cypher逻辑对齐,用match方法手动定义关系匹配规则,无需修改模型定义:
Person.as(:p) .match('(p)-[:HAS_ACCOUNT]->(s:Social)-[:FRIENDS_WITH]->(f:Facebook)') .return('p.name, collect(f.name) as friend_names')
3. 自定义关联末端标签的方法
可以通过两种方式实现标签过滤:
方式1:查询时动态追加标签
使用labels方法给末端节点追加标签限制:
# 仅匹配同时带有Social、Facebook标签的节点 Person.as(:p).socials.labels(:Facebook).where(name: "Someone")
生成的Cypher会自动给socials匹配的节点加上:Facebook标签约束。
方式2:基类新增复用作用域
在Social基类中定义子类过滤的scope,后续可直接链式调用:
class Social include ActiveGraph::Node # 原有代码不变 scope :facebook, -> { labels(:Facebook) } scope :instagram, -> { labels(:Instagram) } end # 调用示例 Person.as(:p).socials.facebook.where(name: "Someone")
内容的提问来源于stack exchange,提问作者Sbunzini
相关产品推荐
相关产品推荐

