Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 168 additions & 10 deletions neo4j-test/example.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,194 @@
import { expect } from 'chai';
import { initDriver, closeDriver } from '../src/neo4j/neo4j-driver.js';
import { addNode } from '../src/neo4j/neo4j-functions';
import { deleteAllNodesAndEdges, getGeneNameById, getNumNodes } from '../src/neo4j/test-functions.js';
import { addEdge, addNode, getInteractions, getNeighbouringNodes, searchByGeneId } from '../src/neo4j/neo4j-functions';
import { deleteAllNodesAndEdges, getGeneName, getNumNodes, getNumEdges, getEdge } from '../src/neo4j/test-functions.js';

describe('Example set of tests', function () {
describe('Tests for addNode, addEdge and seachByGeneId', function () {

before('Should create a driver instance and connect to server', async () => {
await initDriver();
await deleteAllNodesAndEdges();
});

after('Delete nodes and edges, close driver', async function () {
//await deleteAllNodesAndEdges();
after('Close driver', async function () {
await closeDriver();
});

beforeEach('Delete nodes and edges', async function () {
await deleteAllNodesAndEdges();
});

it('Make one node', async function () {
expect(await getNumNodes()).equal(0);
await addNode('ncbigene:5597', 'MAPK6');
expect(await getGeneNameById('ncbigene:5597')).equal('MAPK6');
expect(await getGeneName('ncbigene:5597')).equal('MAPK6');
expect(await getNumNodes()).equal(1);
});

it('Make another node', function () {
it('Make an edge between the two nodes', async function () {
expect(await getNumEdges()).equal(0);
await addNode('ncbigene:207', 'AKT');
await addNode('ncbigene:5597', 'MAPK6');
await addEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b',
'phosphorylation',
'ncbigene:5597',
'ncbigene:207',
'a896d611-affe-4b45-a5e1-9bc560ffceab',
'10.1126/sciadv.abi6439',
'34767444',
'MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');
expect(await getNumEdges()).equal(1);
let edge = await getEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b');
expect(edge.type).equal('INTERACTION');
expect(edge.properties.type).equal('phosphorylation');
expect(edge.properties.sourceId).equal('ncbigene:5597');
expect(edge.properties.targetId).equal('ncbigene:207');
expect(edge.properties.xref).equal('a896d611-affe-4b45-a5e1-9bc560ffceab');
expect(edge.properties.doi).equal('10.1126/sciadv.abi6439');
expect(edge.properties.pmid).equal('34767444');
expect(edge.properties.articleTitle).equal('MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');
});

it('Making a duplicate node fails', async function () {
await addNode('ncbigene:207', 'AKT');
await addNode('ncbigene:5597', 'MAPK6');
expect(await getNumNodes()).equal(2);
await addNode('ncbigene:5597', 'MAPK6');
await addNode('ncbigene:5597', 'This is a dummy name');
expect(await getNumNodes()).equal(2);
expect(await getGeneName('ncbigene:5597')).equal('MAPK6');
});

it('Making a duplicate edge fails', async function () {
await addNode('ncbigene:207', 'AKT');
await addNode('ncbigene:5597', 'MAPK6');
await addEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b',
'phosphorylation',
'ncbigene:5597',
'ncbigene:207',
'a896d611-affe-4b45-a5e1-9bc560ffceab',
'10.1126/sciadv.abi6439',
'34767444',
'MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');
expect(await getNumEdges()).equal(1);
await addEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b',
'phosphorylation',
'ncbigene:5597',
'ncbigene:207',
'a896d611-affe-4b45-a5e1-9bc560ffceab',
'10.1126/sciadv.abi6439',
'34767444',
'MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');
await addEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b',
'This is a dummy type',
'nc7',
'ncbigene:207',
'a896d611-affe-4b45-a5e1-9bc560ffceab',
'10.1126/sciadv.abi6439',
'3444',
'MAPK6-AKT signaling ');
expect(await getNumEdges()).equal(1);
let edge = await getEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b');
expect(edge.type).equal('INTERACTION');
expect(edge.properties.type).equal('phosphorylation');
expect(edge.properties.sourceId).equal('ncbigene:5597');
expect(edge.properties.targetId).equal('ncbigene:207');
expect(edge.properties.xref).equal('a896d611-affe-4b45-a5e1-9bc560ffceab');
expect(edge.properties.doi).equal('10.1126/sciadv.abi6439');
expect(edge.properties.pmid).equal('34767444');
expect(edge.properties.articleTitle).equal('MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');
});

it('Ensure searchGeneById works as expected for MAPK6', async function () {
await addNode('ncbigene:207', 'AKT');
await addNode('ncbigene:5597', 'MAPK6');
await addEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b',
'phosphorylation',
'ncbigene:5597',
'ncbigene:207',
'a896d611-affe-4b45-a5e1-9bc560ffceab',
'10.1126/sciadv.abi6439',
'34767444',
'MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');

let mapk6Relationships = await getInteractions('ncbigene:5597');

expect(mapk6Relationships.length).equal(1);
expect(mapk6Relationships[0].type).equal('INTERACTION');
expect(mapk6Relationships[0].properties.type).equal('phosphorylation');
expect(mapk6Relationships[0].properties.sourceId).equal('ncbigene:5597');
expect(mapk6Relationships[0].properties.targetId).equal('ncbigene:207');
expect(mapk6Relationships[0].properties.xref).equal('a896d611-affe-4b45-a5e1-9bc560ffceab');
expect(mapk6Relationships[0].properties.doi).equal('10.1126/sciadv.abi6439');
expect(mapk6Relationships[0].properties.pmid).equal('34767444');
expect(mapk6Relationships[0].properties.articleTitle).equal('MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');

let mapk6NeighbouringNodes = await getNeighbouringNodes('ncbigene:5597');

expect(mapk6NeighbouringNodes.length).equal(1);
expect(mapk6NeighbouringNodes[0].labels[0]).equal('Gene');
expect(mapk6NeighbouringNodes[0].properties.id).equal('ncbigene:207');
expect(mapk6NeighbouringNodes[0].properties.name).equal('AKT');
});

it('Make an edge between the two nodes', function () {
it('Ensure searchGeneById works as expected for AKT', async function () {
await addNode('ncbigene:207', 'AKT');
await addNode('ncbigene:5597', 'MAPK6');
await addEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b',
'phosphorylation',
'ncbigene:5597',
'ncbigene:207',
'a896d611-affe-4b45-a5e1-9bc560ffceab',
'10.1126/sciadv.abi6439',
'34767444',
'MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');

let aktRelationships = await getInteractions('ncbigene:207');

expect(aktRelationships.length).equal(1);
expect(aktRelationships[0].type).equal('INTERACTION');
expect(aktRelationships[0].properties.type).equal('phosphorylation');
expect(aktRelationships[0].properties.sourceId).equal('ncbigene:5597');
expect(aktRelationships[0].properties.targetId).equal('ncbigene:207');
expect(aktRelationships[0].properties.xref).equal('a896d611-affe-4b45-a5e1-9bc560ffceab');
expect(aktRelationships[0].properties.doi).equal('10.1126/sciadv.abi6439');
expect(aktRelationships[0].properties.pmid).equal('34767444');
expect(aktRelationships[0].properties.articleTitle).equal('MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');

let aktNeighbouringNodes = await getNeighbouringNodes('ncbigene:207');

expect(aktNeighbouringNodes.length).equal(1);
expect(aktNeighbouringNodes[0].labels[0]).equal('Gene');
expect(aktNeighbouringNodes[0].properties.id).equal('ncbigene:5597');
expect(aktNeighbouringNodes[0].properties.name).equal('MAPK6');
});

it('Search for a gene in an empty database yields empty array', async function () {
let nonexistent = await searchByGeneId('ncbigene:207');
expect(nonexistent.length).equal(0);
nonexistent = await getInteractions('ncbigene:207');
expect(nonexistent.length).equal(0);
nonexistent = await getNeighbouringNodes('ncbigene:207');
expect(nonexistent.length).equal(0);
});

it('Ensure searchGeneById works as expected', function () {
it('Search for a non-existing gene in a non-empty database yields empty array', async function () {
await addNode('ncbigene:207', 'AKT');
await addNode('ncbigene:5597', 'MAPK6');
await addEdge('01ef22cc-2a8e-46d4-9060-6bf1c273869b',
'phosphorylation',
'ncbigene:5597',
'ncbigene:207',
'a896d611-affe-4b45-a5e1-9bc560ffceab',
'10.1126/sciadv.abi6439',
'34767444',
'MAPK6-AKT signaling promotes tumor growth and resistance to mTOR kinase blockade.');

let nonexistent = await searchByGeneId('ncbigene:217');
expect(nonexistent.length).equal(0);
nonexistent = await getInteractions('ncbigene:217');
expect(nonexistent.length).equal(0);
nonexistent = await getNeighbouringNodes('ncbigene:217');
expect(nonexistent.length).equal(0);
});

});
3 changes: 2 additions & 1 deletion src/neo4j/.env
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
GRAPHDB_IMAGE_TAG=5.4.0
GRAPHDB_IMAGE_TAG=5.4.0
RETHINKDB_IMAGE_TAG=latest
17 changes: 15 additions & 2 deletions src/neo4j/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version: "3.8"
services:
services:
graphdb:
image: neo4j:${GRAPHDB_IMAGE_TAG:-latest}
restart: unless-stopped
Expand All @@ -18,11 +18,24 @@ services:
NEO4J_PLUGINS: '["apoc"]'
networks:
- graphdb-config-network
db:
image: pathwaycommons/rethinkdb-docker:${RETHINKDB_IMAGE_TAG:-latest}
restart: unless-stopped
container_name: db
ports:
- "8080:8080"
- "28015:28015"
- "29015:29015"
volumes:
- db-data:/data
networks:
- graphdb-config-network

volumes:
graphdb-data:
graphdb-plugins:

db-data:

networks:
graphdb-config-network:
driver: bridge
2 changes: 2 additions & 0 deletions src/neo4j/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// export { addDocumentToNeo4j } from './neo4j-document'; This function does not yet exist
export { addNode, addEdge, searchByGeneId } from './neo4j-functions';
70 changes: 56 additions & 14 deletions src/neo4j/neo4j-functions.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import neo4j from 'neo4j-driver';
import { giveConnectedInfoByGeneId, makeNodeQuery, makeRelationshipQuery } from './query-strings';
import { getDriver } from './neo4j-driver';

/**
* @param { String } id in the form of "dbName:dbId", ex: "ncbigene:207"
* @param { String } name
* @returns
*/
export async function addNode(id, name) {
const driver = getDriver();
let session;
try {
session = driver.session({ database: "neo4j" });
// eslint-disable-next-line no-unused-vars
let result = await session.executeWrite(tx => {
await session.executeWrite(tx => {
return tx.run(makeNodeQuery, {
id: id.toLowerCase(),
name: name
Expand All @@ -23,13 +26,23 @@ export async function addNode(id, name) {
return;
}

/**
* @param { String } id interaction element's UUID (NOT document id)
* @param { String } type
* @param { String } sourceId in the form of "dbName:dbId", ex: "ncbigene:207"
* @param { String } targetId in the form of "dbName:dbId", ex: "ncbigene:207"
* @param { String } xref document UUID
* @param { String } doi
* @param { String } pmid
* @param { String } articleTitle
* @returns
*/
export async function addEdge(id, type, sourceId, targetId, xref, doi, pmid, articleTitle) {
const driver = getDriver();
let session;
try {
session = driver.session({ database: "neo4j" });
// eslint-disable-next-line no-unused-vars
let result = await session.executeWrite(tx => {
await session.executeWrite(tx => {
return tx.run(makeRelationshipQuery, {
id: id.toLowerCase(),
type: type,
Expand All @@ -50,28 +63,57 @@ export async function addEdge(id, type, sourceId, targetId, xref, doi, pmid, art
return;
}

/**
* @param { String } id in the form of "dbName:dbId", ex: "ncbigene:207"
* @returns An object with 2 fields: relationships (array) and neighbouring nodes (array) or null
*/
export async function searchByGeneId(id) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These exported functions should have some documentation (https://jsdoc.app/). There's probably an extension that would create most of this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g.

/**
 * searchPubmed
 * Query the PubMed database for matching UIDs.
 *
 * @param { String } q The query term
 * @param { Object } opts EUTILS ESEARCH options
 * @returns { Object } result The search results from PubMed
 * @returns { Array } result.searchHits A list of PMIDs
 * @returns { Number } result.count The number of searchHits containing PMIDs
 * @returns { String } result.query_key See {@link https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.ESearch|EUTILS docs }
 * @returns { String } result.webenv See {@link https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.ESearch|EUTILS docs }
 */
const searchPubmed = ( q, opts ) => eSearchPubmed( q, opts );

const driver = getDriver();
let session;
let record;
try {
session = driver.session({ database: "neo4j" });
let result = await session.executeRead(tx => {
return tx.run(giveConnectedInfoByGeneId, { id: id });
});
let nodes = result.records.map(row => {
return row.get('m');
});
let edges = result.records.map(row => {
return row.get('r');
});
console.log(nodes);
console.log(edges);
if (result) {
record = result.records;
} else {
record = null;
}
} catch (error) {
console.error(error);
throw error;
} finally {
await session.close();
}
return;
return record;
}

/**
* @param { String } id in the form of "dbName:dbId", ex: "ncbigene:207"
* @returns an array of nodes that are neighbours to the specified gene
*/
export async function getNeighbouringNodes(id) {
let record = await searchByGeneId(id);
if (record.length == 0) {
return record;
}
return record.map(row => {
return row.get('m');
});
}

/**
* @param {*} id in the form of "dbName:dbId", ex: "ncbigene:207"
* @returns an array of relationships leading away from/leading to the specified gene
*/
export async function getInteractions(id) {
let record = await searchByGeneId(id);
if (record.length == 0) {
return record;
}
return record.map(row => {
return row.get('r');
});
}
Loading