1.1.3
Mango is a user/developer-friendly Object-To-Graph Mapper build on top of Neo4j's official JavaScript Driver.
(Object)
Configuration object.
Name | Description |
---|---|
config.engine Engine
|
Instance of an Engine class. If none is supplied, Mango will look for config.engineConfig. If that does not exist or is unusable, a NoEngineError will be thrown. |
config.engineConfig Object
|
Configuration object to instantiate connection to Neo4j. |
config.engineConfig.username string
|
Neo4j DBMS username. |
config.engineConfig.password string
|
Neo4j DBMS password. |
config.engineConfig.ip string?
(default '0.0.0.0' )
|
Neo4j DBMS IP to connect to. |
config.engineConfig.port string?
(default '7687' )
|
Neo4j DBMS port to use |
config.engineConfig.database string?
(default 'neo4j' )
|
Neo4j DBMS database name to use. |
config.builder Builder?
(default newBuilder() )
|
Instance of a Builder class. If none is supplied, a generic one will be instantiated for you. |
const mango = new Mango({
engineConfig: {
username: 'neo4j',
password: 'neo4jpass',
}
}); // connects to Neo4j DBMS instance running on 0.0.0.0:7687 and uses 'neo4j' database
A shortcut to create a search condition.
(string)
Condition for value search ( > < >= <= == etc. ).
(any)
Searched value.
ConditionContainer
:
Main method to search for Nodes in Neo4j. Search granularity: Broadest - by label only Narrow - by label + props
(Object)
A POJO containing key:value to search for matches.
(Object
= {}
)
Configuration object.
Name | Description |
---|---|
config.exactMatch boolean
(default false )
|
{true} Mango searches for exactly what we specified, ie the returned Nodes must not have any extra properties above supplied labels & properties. You get exactly what you asked for.
{false} Mango matches any Nodes that have supplied labels and properties and the returned result may contain Nodes with extra properties. You may get more than you asked for. |
config.returnResult boolean
(default false )
|
{true} returns a Result with additional Neo4j query data.
{false} return Node[]. |
Promise<(Result | Array<Node>)>
:
import { Mango, isEnhancedNode, log } from 'mango';
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
const results: EnhancedNode[] = await mango.findNode(["Person"], { NAME: 'Bob' });
log(results.every(isEnhancedNode)); // true
log(results.length); // 2 <- we found 2 Nodes with NAME == 'Bob'
log(results[0].getProperty("FULL_NAME")); // Bob Dylan
log(results[1].getProperty("FULL_NAME")); // Bob Marley
Builds a Node and merges it into Neo4j.
(Object)
A POJO with properties to construct and merge a Node to Neo4j. !MUST contain at least one label and a REQUIRED property to be unique (Uniqueness Requirement).
Promise<(Result | EnhancedNode)>
:
import { Mango, isEnhancedNode, log } from 'mango';
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
const result: EnhancedNode =
await mango.buildAndMergeNode(["Product"], { NAME: "Sweet Mango" });
log(isEnhancedNode(result)); // true
log(node.isWritten()); // true <- Neo4j has a (Product { NAME: "Sweet Mango", _hash:str, _uuid:str, _date_created: TimeArray })
log(node.getId()); // 1 <- Neo4j's Id for this Node
Builds a Relationship and merges it to Neo4j. Needs no direction, as it is set by the position of startNode & endNode. Namely, (startNode)-[:RELATIONSHIP]->(endNode).
((Node | EnhancedNode))
Node that has an outbound Relationship.
((SimplifiedRelationshipArray | SimplifiedRelationship))
[["REL_TYPES"], "required" | "optional", { relProps } ] | { labels: string[], properties: Object, necessity: "required" | "optional" }.
((Node | EnhancedNode))
Node that has an inbound Relationship.
Promise<(Result | Relationship)>
:
import { Mango, isRelationship, log } from 'mango';
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
// Find Nodes.
const bob = await mango.buildAndMergeNode(["Person"], {
FULL_NAME: "SpongeBob SquarePants",
});
const patrick = await mango.buildAndMergeNode(["Person"], {
FULL_NAME: "Patrick Star",
});
// Build a beautiful friendship!
const relationship = await mango.buildAndMergeRelationship(
bob,
{
labels: ["IS_FRIENDS_WITH"],
properties: { since: "forever" },
}
patrick
);
// Check
// (:Person { FULL_NAME: "SpongeBob SquarePants" })-[:IS_FRIENDS_WITH { since: "forever" }]->(:Person { FULL_NAME: "Patrick Star" })
log(isRelationship(relationship)); // true
log(relationship.isWritten()); // true
Merges EnhancedNode into Neo4j. Separates the building of Nodes/Relationships from their merging stage. You have to build EnhancedNodes with new Builder().buildEnhancedNodes first and then merge with this method.
(EnhancedNode)
EnhancedNode to merge into Neo4j.
Promise<(Result | EnhancedNode)>
:
// This is a long way to do it.
// A shorter is to use mango.buildAndMergeEnhancedNode method.
import { Builder, Mango, isEnhancedNode, log } from 'mango';
const builder = new Builder();
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
// Merge a pattern to Neo4j:
// (:Person { NAME: "SpongeBob" })-[:HAS_FRIEND]->(:Person { NAME: "Patrick" })
const person: EnhancedNode = builder.makeEnhancedNode(
// specify core, or "start", node
builder.makeNode(["Person"], { NAME: "SpongeBob" }),
// specify relationships
[
builder.makeRelationshipCandidate(
["HAS_FRIEND"],
// specify the endNode
builder.makeNode(["Person"], { NAME: "Patrick" })
),
]
);
const enode: EnhancedNode = await mango.mergeEnhancedNode(person);
log(isEnhancedNode(enode)); // true
log(enode.isWritten()); // true
Merges EnhancedNodes into Neo4j. A batch variant of Mango.mergeEnhancedNode.
(Array<EnhancedNode>)
EnhancedNode[] to merge into Neo4j.
Promise<(Result | Array<EnhancedNode>)>
:
import { Builder, Mango, isEnhancedNode, log } from 'mango';
const builder = new Builder();
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
// Merge a pattern to Neo4j:
// (:Person { NAME: "SpongeBob" })-[:HAS_FRIEND]->(:Person { NAME: "Patrick" })
// (:TVSeries { NAME: "SpongeBob SquarePants" })-[:HAS_WIKIPAGE]->(:Webpage { URL: "https://en.wikipedia.org/wiki/SpongeBob_SquarePants" })
const person: EnhancedNode = builder.makeEnhancedNode(
// specify core, or "start", node
builder.makeNode(["Person"], { NAME: "SpongeBob" }),
// specify relationships
[
builder.makeRelationshipCandidate(
["HAS_FRIEND"],
// specify the endNode
builder.makeNode(["Person"], { NAME: "Patrick" })
),
]
);
const wiki: EnhancedNode = builder.makeEnhancedNode(
builder.makeNode(["TVSeries"], { NAME: "SpongeBob SquarePants" }),
[
builder.makeRelationshipCandidate(
["HAS_WIKIPAGE"],
builder.makeNode(["Webpage"], { URL: "https://en.wikipedia.org/wiki/SpongeBob_SquarePants" })
),
]
)
const results: EnhancedNode[] = await mango.mergeEnhancedNodes([person, wiki]);
log(results.every(isEnhancedNode)); // true
log(results[0].isWritten()); // true
log(results[1].isWritten()); // true
Builds and merges EnhancedNode (a subgraph) to Neo4j. Ensures that specified pattern exists in Neo4j. Allows a user-friendly declaration of a graph pattern that needs to be merged into Neo4j.
(SimplifiedEnhancedNode)
Name | Description |
---|---|
$0.labels any
|
|
$0.properties any
|
|
$0.relationships any
|
(Object
= {}
)
(SimplifiedEnhancedNode)
a graph pattern (aka EnhancedNode) to be built and merged into Neo4j.
Promise<(Result | EnhancedNode)>
:
import { Mango, isEnhancedNode, log } from 'mango';
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
// We want SpongeBob and Patrick to be friends:
// (:Person { NAME: "SpongeBob" })-[:HAS_FRIEND]->(:Person { NAME: "Patrick" })
let spongeBob: EnhancedNode = await mango.buildAndMergeEnhancedNode({
labels: ["Person"],
properties: { NAME: "Sponge Bob" },
relationships: [
{
labels: ["HAS_FRIEND"],
partnerNode: { labels: ["Person"], properties: { NAME: "Patrick" } },
},
],
});
log(isEnhancedNode(spongeBob)); // true
log(spongeBob.isWritten()); // true <- pattern is written to Neo4j
// Patterns can be however deep.
// (:City { NAME: "Bikini Bottom" })<-[:LIVES_IN]-(:Person { NAME: "SpongeBob" })-[:HAS_FRIEND]->(:Person { NAME: "Patrick" })-[:LIVES_IN]->(:City { NAME: "Bikini Bottom" })
let bikiniBottom = {
labels: ["City"],
properties: { NAME: "Bikini Bottom" },
};
let spongeBob: EnhancedNode = await mango.buildAndMergeEnhancedNode({
labels: ["Person"],
properties: { NAME: "SpongeBob" },
relationships: [
{
labels: ["LIVES_IN"],
partnerNode: bikiniBottom,
},
{
labels: ["HAS_FRIEND"],
partnerNode: {
labels: ["Person"],
properties: { NAME: "Patrick" },
relationships: [
{
labels: ["LIVES_IN"],
partnerNode: bikiniBottom,
},
],
},
},
],
});
log(isEnhancedNode(spongeBob)); // true
log(spongeBob.isWritten()); // true
log(spongeBob.getParticipatingRelationships()); // 3 <- we merged 3 Relationships
Builds and batch merges multiple EnhancedNodes (aka subgraph) to Neo4j. Allows a user-friendly declaration of a graph pattern that will be merged into Neo4j.
(Array<SimplifiedEnhancedNode>)
(Object
= {}
)
(Array<SimplifiedEnhancedNode>)
a graph pattern (aka EnhancedNodes) to be built and merged into Neo4j.
Promise<(Result | Array<EnhancedNode>)>
:
import { Mango, isEnhancedNode, log } from 'mango';
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
// Create the following pattern in Neo4j:
// (:Person { NAME: "SpongeBob" })-[:HAS_FRIEND]->(:Person { NAME: "Patrick" })
// (:TVSeries { NAME: "SpongeBob SquarePants" })-[:HAS_WIKIPAGE]->(:Webpage { URL: "https://en.wikipedia.org/wiki/SpongeBob_SquarePants" })
let [spongeBob, tvseries]: [EnhancedNode, EnhancedNode] =
await mango.buildAndMergeEnhancedNodes([
// (:Person { NAME: "SpongeBob" })-[:HAS_FRIEND]->(:Person { NAME: "Patrick" })
{
labels: ["Person"],
properties: { NAME: "Sponge Bob" },
relationships: [
{
labels: ["HAS_FRIEND"],
partnerNode: { labels: ["Person"], properties: { NAME: "Patrick" } },
},
],
}
// (:TVSeries { NAME: "SpongeBob SquarePants" })-[:HAS_WIKIPAGE { isToLong: true }]
// ->(:Webpage { URL: "https://en.wikipedia.org/wiki/SpongeBob_SquarePants" })
{
labels: ["TVSeries"],
properties: { NAME: "SpongeBob SquarePants" },
relationships: [
{
labels: ["HAS_WIKIPAGE"],
properties: { isTooLong: true },
partnerNode: {
labels: ["Webpage"],
properties: {
URL: "https://en.wikipedia.org/wiki/SpongeBob_SquarePants"
}
},
},
],
}
]);
log(isEnhancedNode(spongeBob)); // true
log(spongeBob.isWritten()); // true <- pattern is written to Neo4j
log(isEnhancedNode(tvseries)); // true
log(tvseries.isWritten()); // true <- pattern is written to Neo4j
Removes Node/EnhancedNode and all its Relationships from Neo4j.
((Node | EnhancedNode))
Node to delete.
(Object
= {}
)
Configuration object.
Name | Description |
---|---|
config.archiveNodes boolean
(default false )
|
{true} does not actually delete anything from Neo4j. Instead it sets { _isCurrent: false, _dateArchived: TimeArray } on Node & all its Relationships to signify that the Node has been archived and does not represent current state of domain knowledge.
{false} permanently deletes Nodes and all its Relations. |
config.returnResult boolean
(default false )
|
{true} returns a Result.
{false} return deleted EnhancedNode. |
Promise<(Result | EnhancedNode)>
:
import { Mango, log } from 'mango';
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
// mango.findNode returns EnhancedNode[], so we will grab the first result.
const [bob]: EnhancedNode = await mango.findNode(["Person"], { FULL_NAME: 'SpongeBob SquarePants' });
// result is an EnhancedNode that also specifies all Relationships that were affected.
const result: EnhancedNode = await mango.deleteNode(bob);
log(isEnhancedNode(result)); // true
log(result.getProperty('_hasBeenDeleted')); // true
log(result.getProperty('_whenWasDeleted')); // [year, month, day, weekday, timestamp]
log(result.getProperty('_isArchived')); // false
Helper method to classify a POJO's properties into REQUIRED/optional/_private types. Used by Mango to create unique Nodes based on REQUIRED properties.
(Object)
Properties object to decompose.
({requiredProps: Object, optionalProps: Object, privateProps: Object} | [requiredProps, optionalProps, privateProps])
:
import { Mango, isEnhancedNode, log } from 'mango';
const mango = new Mango({
// pass engineConfig with Neo4j credentials
});
const props = {
SOMETHINGIMPORTANT: 'foo',
somethingOptional: 'bar',
_andSomePrivateProp: 'kek'
}
const rv = mango.decomposeProps(props);
log(rv);
// {
// requiredProps: { SOMETHINGIMPORTANT: 'foo' },
// optionalProps: { somethingOptional: 'bar' },
// privateProps: { _andSomePrivateProp: 'kek' },
// }
const rv2 = mango.decomposeProps(props, { asArray: true });
log(rv2);
// [ { SOMETHINGIMPORTANT: 'foo' }, { somethingOptional: 'bar' }, { _andSomePrivateProp: 'kek' } ]
Represents a searched value and its search condition.
(string)
Condition for value search ( > < >= <= == etc. ).
(any)
Searched value.