Янусграф не может понять, как манипулировать данными из запроса Гремлина - PullRequest
0 голосов
/ 14 июня 2019

Я пытаюсь восстановить данные, полученные с помощью гремлинового запроса из графика.Именно у меня возникают проблемы с поиском эффективного способа манипулирования данными, которые возвращаются.

Используемая версия JanusGraph - это 0.3.1, она работает на Cassandra + ES, также она настроена наConfiguredGraphFactory.Так что я могу создавать графики динамически.Я использую gremlin javascript версии 3.4.2 (3.3.3 не работает должным образом)

Я создал небольшой пример, чтобы лучше объяснить, что я имею в виду.График в этих примерах создается без схемы.

Прежде всего, я подключусь к графику с помощью следующих функций:

const gremlin = require('gremlin');

const { Graph } = gremlin.structure;
const { DriverRemoteConnection } = gremlin.driver;

const __ = gremlin.process.statics;
const P = gremlin.process.P;

const GREMLIN_URL = "ws://localhost:8182/gremlin";
const GRAPH_NAME = "graphtest";

let connection;

function getTraversal() {
    const graph = new Graph();
    connection = new DriverRemoteConnection(GREMLIN_URL, { traversalSource: GRAPH_NAME });
    return g = graph.traversal().withRemote(connection);
}

function closeConnection() {
    if(connection && connection.close) connection.close();
}

Затем я создам несколько вершин и ребер,У нас будет один пользователь, два учреждения и два «обученных» ребра, соединяющих пользователя с учреждениями:

async function createVerticesAndEdges() {
    const g = getTraversal();
    const userV = await g.addV('user').property('name', 'Emily').property('identityId', '1234').next();
    console.log('user', userV);
    const institutionV = await g.addV('institution').property('name', 'University of California').property('identityId', 'CA83').next();
    console.log('institution', institutionV);
    const institutionV2 = await g.addV('institution').property('name', 'University of Illinois').property('identityId', 'IL847').next();
    console.log('institution2', institutionV2);
    const trainedE = await g.addE('trained').property('title', 'MS in Computer Science').property('grade', 'B')
        .from_(__.V().has('identityId', '1234')).to(__.V().has('identityId', 'CA83')).next();
    console.log('trained', trainedE);
    const trainedE2 = await g.addE('trained').property('title', 'Political Science').property('grade', 'A')
        .from_(__.V().has('identityId', '1234')).to(__.V().has('identityId', 'IL847')).next();
    console.log('trained2', trainedE2);
    closeConnection();
}

Затем, скажем, я хочу отменить все тренинги, которые пользователь прошел, и я 'Я также хотел бы иметь имя учреждения, в котором проходили обучение.

Итак, запрос, который я запускаю, выглядит так:

async function getUserTrainings() {
    const g = getTraversal();
    const result = await g.V()
        .hasLabel('user')
        .has('identityId', '1234')
        .as('u').outE()
        .hasLabel('trained')
        .inV()
        .path()
        .unfold()
        .where(P.neq('u'))
        .toList();
    closeConnection();
    console.log(result);
}

Это дает мне такой вывод:

[ 
    Edge {
    id: { relationId: 'odxqw-3b4-27th-38o'
        },                                                                                                                                                                                     alber@DESKTOP-8CVHP91 MINGW64 ~/Ref    label: 'trained',
    outV: 4288,
    inV: 4200,
    properties: {}
    },
  Vertex { id: 4200, label: 'institution', properties: undefined
    },
  Edge {
    id: { relationId: 'odxco-3b4-27th-3ao'
        },
    label: 'trained',
    outV: 4288,
    inV: 4272,
    properties: {}
    },
  Vertex { id: 4272, label: 'institution', properties: undefined
    }
]

Это не бит, я мог бы использовать идентификаторы вершин и ребра inV, чтобы восстановить отношения и вернуть данные так, как я хотел, но проблема, как вы видите, в том, что этот запрос не возвращаетсвойства.Так что это вроде бесполезно.

Но затем, просматривая документы gremlin, я нашел шаг valueMap (), так что я могу немного отредактировать предыдущий запрос следующим образом:

async function getUserTrainings() {
    const g = getTraversal();
    const result = await g.V()
        .hasLabel('user')
        .has('identityId', '1234')
        .as('u').outE()
        .hasLabel('trained')
        .inV()
        .path()
        .unfold()
        .where(P.neq('u'))
        .valueMap(true)
        .toList();
    closeConnection();
    console.log(result);
}

И это даетмне этот вывод:

[ 
    Map {
    EnumValue { typeName: 'T', elementName: 'id'
        } => { relationId: 'odxqw-3b4-27th-38o'
        },
    'title' => 'Political Science',
    EnumValue { typeName: 'T', elementName: 'label'
        } => 'trained',
    'grade' => 'A'
    },
  Map {
    'name' => [ 'University of Illinois'
        ],
    EnumValue { typeName: 'T', elementName: 'id'
        } => 4200,
    'identityId' => [ 'IL847'
        ],
    EnumValue { typeName: 'T', elementName: 'label'
        } => 'institution'
    },
  Map {
    EnumValue { typeName: 'T', elementName: 'id'
        } => { relationId: 'odxco-3b4-27th-3ao'
        },
    'title' => 'MS in Computer Science',
    EnumValue { typeName: 'T', elementName: 'label'
        } => 'trained',
    'grade' => 'B'
    },
  Map {
    'name' => [ 'University of California'
        ],
    EnumValue { typeName: 'T', elementName: 'id'
        } => 4272,
    'identityId' => [ 'CA83'
        ],
    EnumValue { typeName: 'T', elementName: 'label'
        } => 'institution'
    }
]

Итак, кроме того факта, что возвращенные данные не совсем ясны (я имею в виду, что такое "typeName: 'T", которое одинаково для каждой вершины?)Теперь я возвращаю свойства, но теряю outV и inV по краям и не могу восстановить данные так, как мне нужно.(поймите, какая вершина связана с ребром).

Полагаю, что я мог бы просто использовать первый запрос без шага valueMap (), а затем для каждой вершины и ребра, которые я получу, сделаю еще одинзапрос для извлечения свойств с использованием идентификаторов.

И это может быть хорошо для простой ситуации, подобной этой, но я не думаю, что это будет действительно эффективно для запросов, которые могут касаться сотен вершин и ребер.

Итак, последний вопрос: каков наиболее эффективный способ восстановления данных по пути, включая свойства вершин и ребер?

1 Ответ

0 голосов
/ 17 июня 2019

Я просто пойду к тому, что я считаю сердцем вашего вопроса, поскольку я думаю, что прямой ответ на этот вопрос может прояснить другие подвопросы:

Допустим, я хочу уйти в отставкувсе тренинги, которые прошел пользователь, и мне также хотелось бы, чтобы название учреждения, в котором проходил тренинг

gremlin> g.V().has('user','identityId', '1234').
......1>   outE('trained').
......2>   project('institution','title','grade').
......3>     by(inV().values('name')).
......4>     by('title').
......5>     by('grade')
==>[institution:University of California,title:MS in Computer Science,grade:B]
==>[institution:University of Illinois,title:Political Science,grade:A]

Один побочный вопрос, который, как я думал, мог бы использовать некоторые пояснения:

что такое "typeName: 'T'", которое одинаково для каждой вершины?

T - это значение перечисления в Gremlin и представляет некоторые основные структурные свойстваграфические элементы, в частности label и id.

...