{"_id":"@artificial-brains/kgraph-x-mongo","name":"@artificial-brains/kgraph-x-mongo","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.3":{"name":"@artificial-brains/kgraph-x-mongo","version":"0.1.3","description":"Generic knowledge graph SDK for Mongoose models to manage nodes and edges.","license":"Apache-2.0","type":"commonjs","main":"src/index.js","types":"types/index.d.ts","keywords":["graph","mongoose","knowledge graph","sdk"],"author":{"name":"Artificial Brains Inc"},"repository":{"type":"git","url":"git+https://github.com/artificial-brains-inc/mongodb-kg.git"},"bugs":{"url":"https://github.com/artificial-brains-inc/mongodb-kg/issues"},"homepage":"https://github.com/artificial-brains-inc/mongodb-kg#readme","peerDependencies":{"mongoose":">=6"},"engines":{"node":">=18"},"_id":"@artificial-brains/kgraph-x-mongo@0.1.3","gitHead":"f1f45c86a110cfa3ba6dcbdc54f89e7db374e786","_nodeVersion":"22.14.0","_npmVersion":"11.4.1","dist":{"integrity":"sha512-jCuc2ZiC+c9iOfUovKsJciN1snvHRrXdlg0vAfSctLg5RpOqxpheylUSsSTuewb0BiqG2sPNwAbYjsZHoQaebQ==","shasum":"e5e719361918f349eeb06b661dd380b207342e97","tarball":"https://registry.npmjs.org/@artificial-brains/kgraph-x-mongo/-/kgraph-x-mongo-0.1.3.tgz","fileCount":9,"unpackedSize":54500,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDDCQG4b7mJ+gwj760zIJC6VemCp/hdszEROcgyO2DHFgIgaqtYffG0xlyG+c4ZO9tdtb5lT+RGEVreKBpsPdJKqYI="}]},"_npmUser":{"name":"artificial-brains","email":"awolf@artificialbrains.ai"},"directories":{},"maintainers":[{"name":"artificial-brains","email":"awolf@artificialbrains.ai"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/kgraph-x-mongo_0.1.3_1760955438197_0.7466645491583854"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-20T10:17:18.112Z","0.1.3":"2025-10-20T10:17:18.392Z","modified":"2025-10-20T10:17:18.648Z"},"maintainers":[{"name":"artificial-brains","email":"awolf@artificialbrains.ai"}],"description":"Generic knowledge graph SDK for Mongoose models to manage nodes and edges.","homepage":"https://github.com/artificial-brains-inc/mongodb-kg#readme","keywords":["graph","mongoose","knowledge graph","sdk"],"repository":{"type":"git","url":"git+https://github.com/artificial-brains-inc/mongodb-kg.git"},"author":{"name":"Artificial Brains Inc"},"bugs":{"url":"https://github.com/artificial-brains-inc/mongodb-kg/issues"},"license":"Apache-2.0","readme":"> **Status:** Experimental – actively evolving.  \n> Feedback, issues, and pull requests are welcome.\n\n\n# Knowledge Graph SDK x MongoDB (by Artificial Brains)\n\nA generic Knowledge Graph SDK for Mongoose. It lets you turn any MongoDB collection into a knowledge graph where documents become nodes and relationships become edges.\nThe SDK wires itself into your Mongoose models through middleware so the graph stays in sync as your data changes.\n\n---\n\n## Demo\n\nA working demo using this SDK is available here:  \n[sdk-kg-x-mongo-mFlix Demo](https://github.com/artificial-brains-inc/mongodb-kg-sdk-mFlix)\n\nThe demo shows how to integrate **@artificial-brains/kgraph-x-mongo** into a real Express + Mongoose app.\n\n---\n\n\n## Features\n\n* Schema-agnostic: works with any model; you provide simple mapping functions.\n* Idempotent upserts: deterministic IDs prevent duplicate nodes or edges.\n* Automatic syncing: changes to your documents are reflected automatically.\n* Bulk resync: rebuilds the graph from existing collections using your bindings.\n* Minimal API: `kgInit`, `createGraphModels`, `bindModel`, `kgBulkSync`.\n\n---\n\n## Installation\n\n```bash\nnpm install mongoose\nnpm install @artificial-brains/kgraph-x-mongo\n```\n\nMongoose is a peer dependency; bring your own compatible version.\n\n---\n\n## Quick Start\n\nThis example uses the **mflix** dataset.\nWe create nodes for `movies` and `users`, and edges linking commenters to the movies via 'comment_on' from the `comments` model.\n\n### 1. Initialize the SDK\n\nTell the SDK which Mongoose models will store your nodes and edges.\n\n```js\nconst mongoose = require('mongoose');\nconst { kgInit } = require('@artificial-brains/kgraph-x-mongo');\n\nconst NodesModel = require('./models/nodes');\nconst EdgesModel = require('./models/edges');\n\nkgInit({\n  nodesModel: NodesModel,\n  edgesModel: EdgesModel\n});\n```\n\n---\n\n### 1a. Auto-create Graph Models (optional)\n\nYou can automatically generate `NodeModel` and `EdgeModel` using `createGraphModels()`. Be aware to index customFields as required to make it efficient (it will be indexed as properties.field). \n\n```js\nconst { createGraphModels, kgInit } = require('@artificial-brains/kgraph-x-mongo');\n\nconst nodeTypes = ['user', 'movie', 'comment', 'theater'];\nconst relationships = ['commented_on', 'screened_at'];\n\nconst { NodeModel, EdgeModel } = createGraphModels({\n  node: {\n    name: 'NodesKG',\n    customFields: {\n      title: { type: String, index: true },\n      year:  { type: String, index: true },\n      name:  { type: String, index: true }\n    },\n    typeEnum: nodeTypes\n  },\n  edge: {\n    name: 'EdgesKG',\n    customFields: {\n      text: { type: String }\n    },\n    relationshipEnum: relationships\n  },\n  connection: mongoose\n});\n\nkgInit({ nodesModel: NodeModel, edgesModel: EdgeModel });\n```\n\nNodes always include:\n`id`, `label`, `type`, `source_collection`, `source_id`.\n\nEdges always include:\n`id`, `source`, `target`.\n\n---\n\n### 2. Bind Your Models\n\n`bindModel()` defines how a document becomes a node and which edges it emits.\nThe SDK attaches middleware to each bound Mongoose model. \n\nIn your model definition (e.g. movies)\n```js\n\n\nconst { bindModel } = require('@artificial-brains/kgraph-x-mongo');\n\n\nconst MovieSchema = new Schema({ /* your schema */});\n\n// Movies → nodes\nbindModel(MovieSchema, {\n    node: (m) => ({\n      id: `movie_${m._id}`,\n      label: m.title || 'Untitled Movie',\n      type: 'movie',\n      source_collection: 'movies',\n      source_id: m._id,\n      properties: { title: m.title, plot: m.plot, year: m.year }\n    }),\n    cleanup: (m) => [{ source: `movie_${m._id}` }, { target: `movie_${m._id}` }]\n  });\n\n//make sure you bind your model before exporting it. \nmodule.exports = mongoose.model('MflixMovie', MovieSchema);\n\n```\n\nExample 2: Edges in your comments model\n\n``` js \n\nconst mongoose = require('mongoose');\nconst { Schema } = mongoose;\nconst { bindModel } = require('@artificial-brains/kgraph-x-mongo');\n\n\nconst CommentSchema = new Schema({\n  /* schema */\n});\n\n\n// Commenter → edge comment → movie\n  bindModel(CommentSchema, {\n    edges: (c) => {\n      const commenter = `user_${c.email}`;\n      const movie     = `movie_${c.movie_id}`;\n      return [{\n        id: `${commenter}_commented_on_${movie}`,\n        source: commenter,\n        target: movie,\n        relationship: 'commented_on',\n        weight: 1, // adjust as necessary\n        properties: { text: c.text ?? null }\n      }];\n    },\n    cleanup: (c) => [{ source: `user_${c.email}` }]\n  });\n\nmodule.exports = mongoose.model('MflixComment', CommentSchema);\n\n```\n\nWhen documents are created, updated, or deleted, the graph updates automatically.\nYou can create nodes and edges in one single bind\n\nbindModel(Schema, {\n  node: (n) => {\n    ...\n  },\n  edges: (e) => {\n    ...\n  }\n})\n\n---\n\n### 3. Sync existing data (one-time build or rebuild)\n\n`kgBulkSync()` can replay your existing bindings to populate or rebuild the graph.\nIt uses your `bindModel()` logic internally, so you don’t have to re-map nodes or edges manually.\nUse only when building the graph for the first time in a database that already contains data. \n\n```js\nconst { kgBulkSync } = require('@artificial-brains/kgraph-x-mongo');\n\nawait kgBulkSync({\n  models: [\n    { model: MflixMovie },\n    { model: MflixUser },\n    { model: MflixComment },\n  ],\n  useBindings: true,    // must be true for initial build\n  batchSize: 2000,     // how many upserts per bulkWrite batch\n  maxPerModel: 0,      // 0 = all\n});\n```\n\nNotes:\n* It simply replays your bindings for each document.\n* You can limit processing with `maxPerModel`.\n\n---\n\n### 4. Query the Graph\n\nExpose your data through a simple API route.\n\n```js\napp.get('/api/graph', async (_req, res) => {\n  const [nodes, edges] = await Promise.all([\n    NodesModel.find({}).lean(),\n    EdgesModel.find({}).lean()\n  ]);\n  res.json({ nodes, edges });\n});\n```\n\nIf querying nodes and edges to diplay the graph, make sure you query one first, and then run a query based on edge's target or source to query the proper relationships between nodes. \n\nYou can visualize data using D3.js, Cytoscape.js, or any other graph library.\nA minimal D3 example is included in `/public/js/graph.js` of the mflix example. \n\n---\n\n### 4A. Query Structural Distance (Unweighted)\n\nYou can calculate the shortest path between any two nodes in your graph using:\n\n``` js \n\nkgShortestPath(startId, endId, options).\n\n```\nThis method measures the number of hops between two entities (ignoring edge weights).\nIt’s useful for exploring degrees of connection — for example, how two users are related through the movies they’ve both commented on.\n\nExample: Find how closely two users are connected through shared movies\n\n```js\n\n\nconst { distance, path } = await MflixComment.kgShortestPath(\n  'user_alice@example.com',\n  'user_bob@example.com',\n  { directed: false, maxDepth: 8 }\n);\n\nconsole.log(distance); // 3\nconsole.log(path);     // [ 'user_alice@example.com', 'movie_Inception', 'user_bob@example.com' ]\n\n```\n\nInterpretation:\n\nThis means Alice and Bob are 3 steps apart in the comment network: Alice → Inception ← Bob.\nIf they had both commented on the same movie, the distance would be 1.\nLonger distances indicate weaker or indirect relationships — for example, two users who share a connection through multiple other users and movies.\n\nUse this to analyze:\n* Communities of users clustered by shared interests.\n* Movie popularity (how many users it connects).\n* Degrees of separation between people or content.\n\n\n\n### 4B. Query Weighted Distance (Semantic)\n\nYou can also calculate the lowest-cost path between two nodes using \n\n``` js\n\nkgWeightedPath(startId, endId, options).\n\n```\n\nWeighted distance considers each edge’s numeric weight (e.g., comment sentiment, frequency, or affinity),\nso it measures strength or similarity rather than just closeness.\n\nExample: Compare two movies based on user overlap and comment sentiment\n\n``` js \n\nconst result = await MflixComment.kgWeightedPath(\n  'movie_Inception',\n  'movie_Interstellar',\n  {\n    directed: true,\n    weightField: 'weight',\n    defaultWeight: 1\n  }\n);\n\nconsole.log(result);\n// → { distance: 2.4, path: [ 'movie_Inception', 'user_42', 'movie_Interstellar' ] }\n\n```\n\nInterpretation:\n\nIn this example, Inception and Interstellar are 2.4 units apart, meaning they share overlapping audiences with moderately strong engagement.\nA smaller number implies stronger similarity or tighter audience connection.\n\nUse this to:\n* Recommend similar movies based on shared users or sentiments.\n* Identify influential users who bridge communities.\n* Detect trend propagation — how opinions or interests travel across the graph.\n\n\n\n### 4C. Generic Recommendations\n\nUse `kgRecommend(startId, options)` to fetch top-k related nodes without writing traversal code.\nBy default, this runs a 2-hop expansion with a fan-out cap of 64 neighbors per node (sorted by descending weight).\n\n```js\nconst items = await AnyBoundModel.kgRecommend('node_X', {\n  mode: 'weighted',            // 'unweighted' | 'weighted' (default: 'unweighted')\n  limit: 5,                    // number of top related nodes to return\n  relationship: 'connected_to',// edge type(s) to traverse\n  direction: 'any',            // 'out' | 'in' | 'any' (default: 'any')\n  targetType: 'nodeType',      // optional node type filter\n  includePath: true,           // return path nodes for explainability (optional)\n  // Advanced options:\n  // metaPath: [\n  //   { relationship: 'rated', direction: 'out' },\n  //   { relationship: 'belongs_to', direction: 'in' }\n  // ],\n});\n\n\n```\nNotes:\n* In current version, if multiple neighbors share the same weight, the order is deterministic (index order).\n\n\n\n## API Reference\n\n### kgInit(options)\n\nInitializes the SDK.\n\n| Option     | Type           | Description                                                          |\n| ---------- | -------------- | -------------------------------------------------------------------- |\n| nodesModel | Mongoose model | Required. Stores graph nodes.                                        |\n| edgesModel | Mongoose model | Required. Stores graph edges.                                        |\n| repos      | Object         | Optional. Additional repositories accessible in `edges()` functions. |\n\n---\n\n### bindModel(model, config)\n\nAttaches middleware so your model automatically updates the graph.\n\n| Key             | Type     | Required | Description                                                                |\n| --------------- | -------- | -------- | -------------------------------------------------------------------------- |\n| node(doc)       | Function | Yes      | Returns a node object; must include a unique string `id`.                  |\n| edges(doc, ctx) | Function | No       | Returns an array of edges.                                                 |\n| cleanup(doc)    | Function | No       | Returns filters for removing nodes and edges when the document is deleted. |\n\n---\n\n### createGraphModels(options)\n\nBuilds `NodeModel` and `EdgeModel` schemas with defaults and indexes.\nReturns `{ NodeModel, EdgeModel }`.\n\n| Option                | Type                | Description                                     |\n| --------------------- | ------------------- | ----------------------------------------------- |\n| node.name             | String              | Name of the node model (default: `GraphNode`).  |\n| node.customFields     | Object              | Additional fields for node `properties`.        |\n| node.typeEnum         | Array               | Allowed values for the `type` field (optional). |\n| edge.name             | String              | Name of the edge model (default: `GraphEdge`).  |\n| edge.customFields     | Object              | Additional fields for edge `properties`.        |\n| edge.relationshipEnum | Array               | Allowed `relationship` values (optional).       |\n| connection            | Mongoose connection | Optional; defaults to global connection.        |\n\n---\n\n### kgBulkSync(options)\n\nSynchronizes or rebuilds your knowledge graph.\n\n#### Resync mode (recommended)\n\nReplays all your bindings across existing documents.\n\n| Option      | Type   | Default  | Description                           |\n| ----------- | ------ | -------- | ------------------------------------- |\n| models      | Array  | []       | Array of `{ model, query?, label? }`. |\n| useBinding  | Boolean| false    | true required for initial build       |\n| batchSize   | Number | 1000     | Number of documents to sync.          |\n| maxPerModel | Number | 0        | Max docs to sync per model            |\n\n\n#### Classic upsert mode (deprecated)\n\nManually upserts nodes and edges.\n\n| Option       | Type   | Description                        |\n| ------------ | ------ | ---------------------------------- |\n| desiredNodes | Array  | Array of node objects.             |\n| desiredEdges | Array  | Array of edge objects.             |\n| keepExtra    | Object | `{ edges: true }` to skip pruning. |\n\nUse this only for legacy scripts.\nFuture versions focus on the resync flow.\n\n\n---\n\n## License\n\nApache 2.0  \n\nCreated by [@artificialbrains.ai](https://artificialbrains.ai).\nFollow us on [@alexanderawolf](https://x.com/alexanderawolf)  \n\nIf this SDK helps your project, consider supporting its continued development:  \n[Support via Stripe](https://buy.stripe.com/fZufZi0wL6fG2ef79g7Zu00)  \n\nIf you use this SDK in your project, a link back is appreciated.\n\nPull requests and forks are welcome.\n\n\n---\n\n\n## About Artificial Brains\n\nArtificial Brains is a Research and Innovation Lab accelerating human adoption of neuromorphic technologies.\n\nWhile our research and vision looks far ahead, we release along the way (open source or subscription-first) \nwhenever our progress can strengthen today’s ecosystems and it's transition to neuromorphic-native tech.\n\nJoin the ecosystem to access training, early releases, research, and tools shaping neuromorphic technology:\n[@artificialbrains.ai](https://artificialbrains.ai) ","readmeFilename":"README.md","_rev":"1-a3dc88746632cb8b87004edaa7f4ea59"}