Skip to content

libraz/node-mygramdb-client

Repository files navigation

mygramdb-client

CI npm codecov License

Node.js client library for MygramDB — a high-performance in-memory full-text search engine with MySQL replication support.

Compatible with MygramDB v1.6 (BM25 scoring, HIGHLIGHT, FUZZY, FACET).

Overview

MygramDB provides 25-200x faster full-text search than MySQL FULLTEXT. This client supports both a pure JavaScript implementation and optional C++ native bindings for maximum performance.

MySQL FULLTEXT MygramDB
Search Speed Baseline 25-200x faster
Storage On-disk In-memory
Replication MySQL binlog
Protocol MySQL TCP (memcached-style)

Features

  • Dual Implementation — Optional C++ native bindings with automatic JavaScript fallback
  • Search Expression Parser — Web-style search syntax (+required, -excluded, "phrase", OR, grouping)
  • Full Protocol Support — All MygramDB commands (SEARCH, COUNT, GET, INFO, etc.)
  • Type Safety — Full TypeScript definitions
  • Promise-based API — Modern async/await interface

Installation

npm install mygramdb-client

Or use yarn/pnpm:

yarn add mygramdb-client
pnpm add mygramdb-client

Quick Start

import { createMygramClient, simplifySearchExpression } from 'mygramdb-client';

const client = createMygramClient({
  host: 'localhost',
  port: 11016
});

await client.connect();

// Search
const results = await client.search('articles', 'hello');
console.log(`Found ${results.totalCount} results`);

// Count
const count = await client.count('articles', 'technology');

// Get document by ID
const doc = await client.get('articles', '12345');

client.disconnect();

Search Expressions

Parse web-style search queries into structured search parameters:

import { simplifySearchExpression } from 'mygramdb-client';

// Space = AND, - = NOT, "" = phrase, OR = OR, () = grouping
const expr = simplifySearchExpression('hello world -spam');
// → { mainTerm: 'hello', andTerms: ['world'], notTerms: ['spam'] }

const results = await client.search('articles', expr.mainTerm, {
  andTerms: expr.andTerms,
  notTerms: expr.notTerms,
  limit: 100,
  offset: 50,
  filters: { status: 'published', lang: 'en' },
  sortColumn: 'created_at',
  sortDesc: true
});

MygramDB v1.6 Features

BM25 Relevance Scoring

Sort by relevance using the special _score sort column (requires verify_text: ascii|all on the server):

const results = await client.search('articles', 'machine learning', {
  sortColumn: '_score',
  sortDesc: true,
  limit: 10
});

Fuzzy Search (Levenshtein)

// Allow up to 1 edit (default) or 2 edits.
const results = await client.search('articles', 'machne', {
  fuzzy: 1,
  limit: 10
});

Highlighting

const results = await client.search('articles', 'golang', {
  highlight: {
    openTag: '<strong>',
    closeTag: '</strong>',
    snippetLen: 200,
    maxFragments: 3
  },
  sortColumn: '_score',
  sortDesc: true,
  limit: 10
});

for (const r of results.results) {
  console.log(r.primaryKey, r.snippet);
}

Pass an empty {} to enable highlighting with server defaults (<em>/</em>, 100 code points, up to 3 fragments).

Facets

Aggregate distinct filter-column values with document counts. Optionally scope the aggregation to a search result set:

// All distinct statuses:
const all = await client.facet('articles', 'status');

// Top categories among documents matching "machine learning":
const top = await client.facet('articles', 'category', {
  query: 'machine learning',
  filters: { status: '1' },
  limit: 10
});

for (const v of top.results) {
  console.log(`${v.value}: ${v.count}`);
}

MygramDB v1.7 Features

Multi-database (qualified table identity)

A v1.7+ instance can index tables from more than one database. Reference a table as database.table; bare names still work on single-database servers.

await client.search('app_db.articles', 'hello');

import { qualifyTableIdentity, parseTableIdentity } from 'mygramdb-client';
qualifyTableIdentity('articles', 'app_db'); // 'app_db.articles'
parseTableIdentity('app_db.articles');      // { database: 'app_db', table: 'articles' }

Boolean search

search() sends the query as a single (auto-quoted) token. For boolean AND/OR/NOT/grouping, build the expression and pass it to searchRaw():

import { convertSearchExpression } from 'mygramdb-client';

const raw = convertSearchExpression('python OR (ruby AND rails)');
const res = await client.searchRaw('articles', raw, { limit: 50 });

Runtime variables and on-demand sync

await client.setVariable('logging.level', 'info');
console.log(await client.showVariables('logging%'));

await client.sync('app_db.articles');
console.log(await client.syncStatus());
await client.syncStop('app_db.articles');

TypeScript

Full type definitions are included:

import type {
  ClientConfig,
  SearchResponse,
  CountResponse,
  Document,
  ServerInfo,
  SearchOptions
} from 'mygramdb-client';

Development

yarn install      # Install dependencies
yarn build        # Build library
yarn test         # Run tests
yarn lint         # Lint and format check
yarn lint:fix     # Auto-fix lint + format issues

License

MIT

About

Node.js client library for MygramDB - High-performance in-memory full-text search engine

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors