2014-06-17 11 views
5

Java'dan Neo4J'de cypher parametresinde sorun yaşıyorum. Katıştırılmış veritabanını çalıştırıyorum.Neo4J'de, Java'dan bir cypher sorgusunda etiketin nasıl parametre olarak ayarlanacağı?

kod böyle olmalı (GraphDB.cypher ExecutionEngine doğrudan gider)

HashMap<String, Object> parameter = new HashMap<>(); 
parameter.put("theLabel1", "Group"); 
parameter.put("theRelation", "isMemberOf"); 
parameter.put("theLabel2", "Person"); 
GraphDB.cypher("MATCH (n1:{theLabel1})-[r:{theRelation}]->(n2:{theLabel2}) RETURN n1, r, n2", parameter); 

ancak bu istisna

Exception in thread "main" Invalid input '{': expected whitespace or a label name (line 1, column 11) 
"MATCH (n1:{theLabel1})-[r:{theRelation}]->(n2:{theLabel2}) RETURN n1, r, n2" 

belgeleri (ve öğretici) biten kullanmak söyler Parametreleri kapsayacak şekilde {}, ancak bu özellikler için de cypher json notasyonu olarak kullanılır. @See http://docs.neo4j.org/chunked/milestone/tutorials-cypher-parameters-java.html

GraphDB.cypher("MATCH (n:" + labelName + ")-[r:" + relationName + "]->... 

hedefi etiketi değiştirebilir ve ben istediğim için bu gereklidir, bu sorunu çözmek yerine (diğer şablon yöntemleri veya birlikte) böyle sorgu dizesi oluşturmak için başka bir yolu var mı Kodu tamamen yeniden kullanmak için.

Şimdiden teşekkürler.

[[aldıktan sonra düzenlenen bir (iç) HAYIR CEVAP] AS] parametresinin bu form şu anda (2014,6) desteklenmediği

, hemen sorgu göndermeden önce küçük bir Replacer çalışacaktır.

HashMap<String, Object> parameter = new HashMap<>(); 
parameter.put("theLabel1", "Group"); 
parameter.put("theRelation", "isMemberOf"); 
parameter.put("theLabel2", "Person"); 

parameter.put("aName", "Donald Duck"); 

GraphDB.cypher("MATCH (n1:#theLabel1#)-[r:#theRelation#]->(n2:#theLabel2#) WHERE n2.Name = {aName} RETURN n1, r, n2", parameter); 

... with ... 

public static ExecutionResult cypher(String query, Map<String, Object> params) { 
    for (String key : params.keySet()) { 
     query = query.replaceAll("#" + key + "#", String.valueOf(params.get(key))); 
    } 
    return params == null ? cypherEngine.execute(query) : cypherEngine.execute(query, params); 
} 

Ben şu anda desteklenmemektedir korkuyorum daha readble

+0

Eh, fakat bu özelliklerin bu tür sağlamak için Neo4j kapsam dışında biraz öyle, yapma sence? – Rolf

+0

@Raxa, çözümünüz "değiştirici" ile çok ilginç. İlk bakışta, "# theLabel1 #" kullanımınız statik görünüyor, bu nedenle Cypher 'label'' '' '' 'parametresi '' nin dinamik olarak belirtilmesiyle ilgili gerçek meseleyi ele almadı. Ancak "parametre" deki eşlemenin yerini alacak bir yer tutucu olarak düşünüldüğünde, dinamik olarak "etiket" kelimesini geçmeyi başarır.Herhangi bir standart çözüm olup olmadığından emin değilsiniz, ancak bu oldukça ilginç bir azaltmadır. – Causality

cevap

5

olabilir.

Ve bu sorunla açıklanan aynı nedenlerden dolayı olabilir: https://github.com/neo4j/neo4j/pull/1542.

Parametrized sorgularının arkasındaki fikir, (önbellek) yürütme planlarını yeniden kullanmaktır. Bir düğüm etiketi veya ilişki tipi değişirse, yürütme planı hiç aynı olmaz ve bu nedenle yürütme planı önbelleğinin kullanılabilirliğini bozar.

+1

Neo4J dokümantasyonunun bize 7.5'deki fikri sattığı konusunda utanç verici. "Bu, geliştiricilerin bir sorgu oluşturmak için string oluşturma işlemine başvurmak zorunda olmadıkları anlamına geliyor." Açıkçası bu gerçek bir motivasyon değil. Cypher motorunun bu işi yapması ve yukarıdaki gibi yukarıdaki gibi değiştirmeler yapması daha mantıklı olurdu. Geliştiriciler daha sonra sorguları tam olarak parametreleştirebilir ve Neo4J zamanla geliştikçe, bu parametreden yararlanabileceği şekilde yararlanabilir. – Herc

+0

Bir sorun açmaktan çekinmeyin: https://github.com/neo4j/neo4j/issues :) – Rolf

4

Sadece ben aynı şeyin içine koşuyordu olarak bunu yapmanın bir yolunu:

MATCH (n) WHERE {label} IN labels(n) 

etiketler() işlevi listedeki varlığı için bir düğüm üzerinde tüm etiketleri ve IN operatörü testleri döndürür . Görünüşe göre Cypher, bu yapının, yüklemedeki değişken alandaki bir parametreyi kullanmasından dolayı izin verir. Cypher belgelerine göre, WHERE maddelerindeki etiketler veya özellikler ile düğüm özniteliğinde doğrudan özellik/etiket katsayıları aynı şekilde optimize edilir, bu nedenle önemli bir performans artışı olmamalıdır.

evet, statik sorgu şablonları tanımlayabilirsiniz

birden olası etiketleri desteklemek için kolay bir yol hakkında emin değil ...

+1

Harika ve basit bir yanıt. Genius! Sadece bu cevabı tamamlamak için, aynı ilişkiyi de yapmak isterseniz, TYPE yerleşik fonksiyonunu kullanmanız gerekir, örn .: 'MATCH (a) - [r] -> (b) WHERE {relName} = TYPE (r) RETURN ID (r) AS relId, TYPE (r) AS relName' – artemisian

+0

'Any()' işlevini kullanarak birden çok etiketi destekleyebilirsiniz. Örneğin, MATCH (o) HERHANGİ BİR NEREDE (item IN etiketler (o) NUMARALI öğe IN $ list_of_labels) – John

+0

, ancak herhangi bir optimizasyon yoktur, etiketle bir arama bir etiket iken, düğüm başına çek içeren tam bir veritabanı taraması olacaktır. -Spor mağazası işletimi cypher sorgunuzu dinamik olarak yapılandırabilir ve ardından .e.g. uygulamak için apoc.cypher.run kullanın –