2015-06-08 2 views
1

Я пытаюсь написать поисковый запрос, где на входе находится какой-либо ключ поиска, а требование - искать среди вершин, где данный ключ ввода соответствует значению двух или более ключи свойств вершины. Для примера при условии, что у меня есть вершины пользователя в моем графике дб со следующими ключами собственности:Поиск запроса Gremlin по ключевому слову поиска по нескольким свойствам вершин

  • 1) Пользователь первое имя
  • 2) Пользователь фамилия
  • 3) электронной почты пользователя

Теперь, учитывая ключ поиска «xyz», мне нужно выполнить поиск по пользовательским вершинам, где любой из указанных выше трех ключей свойств соответствует значению «xyz». Вот как я подошел к проблеме.

g.V.has('ENTITY_TYPE', 'USER').or(_().has('USER_EMAIL' , TEXT.REGEX , '.*xyz.*') , _().has('USER_FNAME' , TEXT.REGEX , '.*xyz.*''USER_EMAIL' , TEXT.REGEX , '.*xyz.*') , _().has('USER_LNAME' , TEXT.REGEX , '.*xyz.*')).dedup(); 

Я создал необходимые смешанные индексы (три отдельные смешанные индексы) для USER_EMAIL, USER_FNAME и USER_LNAME следующим образом:

key = m.makePropertyKey("USER_EMAIL").dataType(String.class).make(); 
m.buildIndex("serachbyemail",Vertex.class).addKey(key).buildMixedIndex("search"); 

key = m.makePropertyKey("USER_FNAME").dataType(String.class).make(); 
m.buildIndex("searchbyfname",Vertex.class).addKey(key).buildMixedIndex("search"); 

key = m.makePropertyKey("USER_LNAME").dataType(String.class).make(); 
m.buildIndex("typemixed",Vertex.class).addKey(key).buildMixedIndex("search"); 

Это прекрасно работает. Но я хочу знать, является ли это наилучшим подходом к этой проблеме? Или есть лучший способ сделать это? Кроме того, я использую gremlin java api для написания вышеуказанного запроса. Я использую dedup() для удаления повторяющихся вершин.

+0

Пожалуйста, добавьте определение (определения) индекса. –

+0

Обновлено сообщение с определениями индексов – user3244615

ответ

2

3 индекса не помогут эффективно ответить на ваш запрос. Лучше создать единый индекс, который охватывает все 3 поля (это не означает, что ваш запрос должен иметь условия для всех полей) и выдает прямой запрос индекс:

Пример графика:

g = TitanFactory.open("conf/titan-cassandra-es.properties") 
m = g.getManagementSystem() 

user = m.makeVertexLabel("USER").make() 
email = m.makePropertyKey("USER_EMAIL").dataType(String.class).make() 
fname = m.makePropertyKey("USER_FNAME").dataType(String.class).make() 
lname = m.makePropertyKey("USER_LNAME").dataType(String.class).make() 

m.buildIndex("users", Vertex.class).addKey(email).addKey(fname).addKey(lname).indexOnly(user).buildMixedIndex("search") 
m.commit() 

ElementHelper.setProperties(g.addVertexWithLabel("USER"), "USER_EMAIL", "[email protected]", "USER_FNAME", "foo", "USER_LNAME", "bar") 
ElementHelper.setProperties(g.addVertexWithLabel("USER"), "USER_EMAIL", "[email protected]", "USER_FNAME", "foo", "USER_LNAME", "bar") 
ElementHelper.setProperties(g.addVertexWithLabel("USER"), "USER_EMAIL", "[email protected]", "USER_FNAME", "foo", "USER_LNAME", "xyz") 
ElementHelper.setProperties(g.addVertexWithLabel("USER"), "USER_EMAIL", "[email protected]", "USER_FNAME", "xyz", "USER_LNAME", "bar") 
ElementHelper.setProperties(g.addVertexWithLabel("USER"), "USER_EMAIL", "[email protected]", "USER_FNAME", "xyz", "USER_LNAME", "xyz") 

g.commit() 

Прямой индекс запроса:

gremlin> g.indexQuery("users", 'v."USER_EMAIL":/.*xyz.*/ v."USER_FNAME":/.*xyz.*/ v."USER_LNAME":/.*xyz.*/').vertices()*.getElement()._().map() 
==>{USER_FNAME=xyz, USER_LNAME=xyz, [email protected]} 
==>{USER_FNAME=xyz, USER_LNAME=bar, [email protected]} 
==>{USER_FNAME=foo, USER_LNAME=xyz, [email protected]} 
==>{USER_FNAME=foo, USER_LNAME=bar, [email protected]} 

Как вы можете видеть, что я также заменил ENTITY_TYPE с меткой вершины. Метка может помочь сохранить индекс как можно меньше. Если, например, другой тип вершин (например, PROFILE) также использует свойство USER_EMAIL, он не попадает в индекс (если он был создан с использованием .indexOnly(user)).

+0

Большое спасибо Даниэлю. Я попробовал это, и результаты намного лучше. Может ли этот индекс работать с запросом гремлина? Если да, будет ли он столь же эффективным, как прямой запрос индекса? Есть ли способ добавить вершинную метку к существующим пользовательским вершинам? Если перед достижением вершин пользователя (Вершины УНИВЕРСИТЕТА -> ОТДЕЛЫ вершин -> Версии USER) требуется некоторая обходная процедура, а затем применение ключа поиска, есть ли способ достичь этого в запросе прямого индекса. – user3244615

+1

К сожалению, это невозможно с помощью Gremlin. Он будет работать с условиями AND, но OR'ing не будет использовать индекс. Хотя я не уверен, что Titan 0.9 уже может это сделать. Этикетки вершин неизменяемы; вы можете создать только новую вершину, скопировать свойства и ребра из старой вершины и затем отбросить старую вершину. Как и любой запрос глобального индекса, прямые запросы индекса не могут использоваться в середине опроса. В этом случае вы хотели бы использовать простой шаг '.or()'. –

+0

Еще раз спасибо! Значит ли это, что мы не можем использовать смешанные индексы в приведенном выше сценарии, где требуется обход? – user3244615