2014-09-18 5 views
0

Я построил базу данных Neo4j, содержащую около 50 000 узлов с меткой DIAGNOSE, каждая из которых имеет свойство TEXT с длиной до 50 символов. В той же базе данных графа содержится около 120 000 узлов с меткой BASETEXT, каждая из которых имеет свойство string TEXTVALUE с числом символов до 175 000 символов. Моя цель - создать связь (b: BASETEXT) - [: ASSOCIATED] -> (d: DIAGNOSE) в случае, если DIAGNOSE.TEXT включен в BASETEXT.TEXTVALUE - в результате получается всего около 2.9 * 10^9 запросов. Я попытался следующие два подхода шифра:создание отношений через полнотекстовый поиск в Neo4J

подход 1:

match (b:BASETEXT), (d:DIAGNOSE) 
where b.TEXTVALUE =~ (".* " + d.TEXT + " .*") 
merge (b) -[:ASSOCIATED]-> (d); 

подход 2 (создать связь между каждым Диагностировать узел и каждый BASETEXT узел, если текст в TEXTVALUE присвоить истинное значение для отношений собственности, СОДЕРЖАЩИМСЯ , в противном случае значение лОЖЬ, наконец, удалить все отношения с ASSOCIATED.CONTAINED = ложным):

match (b:BASETEXT), (d:DIAGNOSE) 
where not (b) -[:ASSOCIATED]-> (d) 
with b, d limit 20000 
create (b) -[a:ASSOCIATED]-> (d) 
with b, d, a 
set a.CONTAINED = 
case 
when (b.TEXTVALUE =~ (".* " + d.TEXT + " .*")) then true 
else false 
end 
return count(a); 

Ни один из упомянутых выше подходов работ. Подход 1 не находит конца в течение получаса, подход 2 находит конец, но мне потребуется 60 дней. Любые предложения по правильному внедрению текстового поиска в Neo4J и решению проблемы - желательно в Cypher?

+0

Не используйте regex, но используйте индексы наследия Lucene для полнотекстового поиска: см., например. http://jexp.de/blog/2014/03/full-text-indexing-fts-in-neo4j-2-0/ – tstorms

+0

был вебинар по классификации документов, записанный на http://player.vimeo.com/видео/105266385. Наверное, это похоже на ваш случай использования. –

ответ

0

Я также создал graph-gist for it, for illustration.

Я думаю, что это прецедент, который еще не поддерживается в cypher.

Если вы хотите попробовать простой Cypher вариант, который должен работать (но медленно) попробуйте это:

MATCH (d:DIAGNOSE) 
WHERE NOT() -[:ASSOCIATED]-> (d) 
WITH d 
SKIP 0 LIMIT 1000 
MATCH (b:BASETEXT) 
WHERE (b.TEXTVALUE =~ (".* " + d.TEXT + " .*")) 
CREATE (b) -[:ASSOCIATED]-> (d) 
RETURN count(*); 

Это должно быть гораздо быстрее сделать в Java:

public class ConnectIndexTest { 
    private static final String PATH = "target/connect.db"; 
    public static final Label BASETEXT = DynamicLabel.label("BASETEXT"); 
    public static final Label DIAGNOSE = DynamicLabel.label("DIAGNOSE"); 
    public static final String TEXTVALUE = "TEXTVALUE"; 
    public static final String TEXT = "TEXT"; 
    public static final String INDEX_NAME = "basetext"; 
    private static final RelationshipType ASSOCIATED = DynamicRelationshipType.withName("ASSOCIATED"); 
    private GraphDatabaseService db; 

    @Before 
    public void setUp() throws Exception { 
//  db = new GraphDatabaseFactory().newEmbeddedDatabase(PATH); 
     db = new TestGraphDatabaseFactory().newImpermanentDatabase(); 
     try (Transaction tx = db.beginTx()) { 
      for (int i = 100_000; i < 250_000; i++) db.createNode(BASETEXT).setProperty(TEXTVALUE, "foo " + i + " bar"); 
      tx.success(); 
     } 
     try (Transaction tx = db.beginTx()) { 
      for (int i = 100_000; i < 250_000; i += 2) db.createNode(DIAGNOSE).setProperty(TEXT, String.valueOf(i)); 
      tx.success(); 
     } 
    } 

    // 120k BASETEXT Nodes 
    // 50k DIAGNOSE Nodes 
    @Test 
    public void testConnect() throws Exception { 
     GlobalGraphOperations ops = GlobalGraphOperations.at(db); 
     try (Transaction tx = db.beginTx()) { 
      Index<Node> index = db.index().forNodes(INDEX_NAME, LuceneIndexImplementation.FULLTEXT_CONFIG); 
      for (Node baseText : ops.getAllNodesWithLabel(BASETEXT)) { 
       index.add(baseText, TEXTVALUE, baseText.getProperty(TEXTVALUE)); 
      } 
      tx.success(); 
     } 
     int count = 0; 
     Transaction tx = db.beginTx(); 
     try { 
      Index<Node> index = db.index().forNodes(INDEX_NAME); 
      for (Node diagnose : ops.getAllNodesWithLabel(DIAGNOSE)) { 
       String text = (String) diagnose.getProperty(TEXT); 
       IndexHits<Node> hits = index.query(TEXTVALUE, "\"" + text + "\"");// quote in case text contains spaces 
       for (Node baseText : hits) { 
        baseText.createRelationshipTo(diagnose, ASSOCIATED); 
        // batch transaction 
        if (++count % 50000 == 0) { 
         System.out.println("count = " + count); 
         tx.success(); 
         tx.close(); 
         tx = db.beginTx(); 
        } 
       } 
      } 

      tx.success(); 
     } finally { 
      tx.close(); 
     } 
     System.out.println("count = " + count); 
    } 
} 
Смежные вопросы