min

mingo

MongoDB query language for in-memory objects

Showing:

Popularity

Downloads/wk

109K

GitHub Stars

766

Maintenance

Last Commit

2mos ago

Contributors

24

Package

Dependencies

0

License

MIT

Type Definitions

Built-In

Tree-Shakeable

Yes?

Categories

Readme

mingo

MongoDB query language for in-memory objects

license version build status issues codecov quality: Javascript alerts npm downloads

Install

$ npm install mingo

Features

For documentation on using query operators see mongodb

Browse package docs for modules.

Usage

// Use as es6 module
import mingo from "mingo";

// or vanilla nodeJS
const mingo = require("mingo");

Default exports and operators

The default export of the main module only includes Aggregator, Query, aggregate(), find(), and remove().

Only Query and Projection operators are loaded by default when using the main module. This is done using the side-effect module mingo/init/basic, and also automatically includes pipeline operators $project, $skip, $limit, and $sort.

If your application uses most of the available operators or you do not care about bundle size, you can load all operators as shown below.

// Note that doing this effectively imports the entire library into your bundle and unused operators cannot be tree shaked
import "mingo/init/system";

Or from the node CLI

node -r 'mingo/init/system' myscript.js

Importing submodules

Submodule imports are supported for both ES6 and ES5.

The following two examples are equivalent.

ES6

This work natively in typescript since it knows how to load commonJS modules as ES6. You may optionally install the esm module to use this syntax.

import { $unwind } from "mingo/operators/pipeline";

ES5

Unlike the ES6 version, it is necessary to specify the operator module in the path to avoid loading any extras

const $unwind = require("mingo/operators/pipeline/unwind").$unwind;

Enabling Operators

To support tree-shaking, you may import and register specific operators that will be used in your application.

import { useOperators, OperatorType } from "mingo/core";
import { $trunc } from "mingo/operators/expression";
import { $bucket } from "mingo/operators/pipeline";

useOperators(OperatorType.EXPRESSION, { $trunc, $floor });
useOperators(OperatorType.PIPELINE, { $bucket });

Using query object to test objects

import { Query } from "mingo";

// create a query with criteria
// find all grades for homework with score >= 50
let query = new Query({
  type: "homework",
  score: { $gte: 50 },
});

// test if an object matches query
query.test(doc);

Searching and Filtering

import { Query } from "mingo";

// input is either an Array or any iterable source (i.e Object{next:Function}) including ES6 generators.
let criteria = { score: { $gt: 10 } };

let query = new Query(criteria);

// filter collection with find()
let cursor = query.find(collection);

// alternatively use shorthand
// cursor = mingo.find(collection, criteria)

// sort, skip and limit by chaining
cursor.sort({ student_id: 1, score: -1 }).skip(100).limit(100);

// count matches. exhausts cursor
cursor.count();

// classic cursor iterator (old school)
while (cursor.hasNext()) {
  console.log(cursor.next());
}

// ES6 iterators (new cool)
for (let value of cursor) {
  console.log(value);
}

// all() to retrieve matched objects. exhausts cursor
cursor.all();

Using $jsonSchema operator

To use the $jsonSchema operator, you must register your own JsonSchemaValidator in the options. No default implementation is provided out of the box so users can use a library with their preferred schema format.

The example below uses Ajv to implement schema validation.

import { RawObject } from "mingo/types"
import { JsonSchemaValidator } from "mingo/core"
import Ajv, { Schema } from "ajv"

const jsonSchemaValidator: JsonSchemaValidator = (s: RawObject) => {
  const ajv = new Ajv();
  const v = ajv.compile(s as Schema);
  return (o: RawObject) => (v(o) ? true : false);
};

const schema = {
  type: "object",
  required: ["item", "qty", "instock"],
  properties: {
    item: { type: "string" },
    qty: { type: "integer" },
    size: {
      type: "object",
      required: ["uom"],
      properties: {
        uom: { type: "string" },
        h: { type: "number" },
        w: { type: "number" },
      },
    },
    instock: { type: "boolean" },
  },
};

// queries documents using schema validation
find(docs, { $jsonSchema: schema }, {}, { jsonSchemaValidator }).all();

Note: An error is thrown when the $jsonSchema operator is used without a the jsonSchemaValidator configured.

Aggregation Pipeline

import { Aggregator } from "mingo/aggregator";
import { useOperators, OperatorType } from "mingo/core";
import { $match, $group } from "mingo/operators/pipeline";
import { $min } from "mingo/operators/accumulator";

// ensure the required operators are preloaded prior to using them.
useOperators(OperatorType.PIPELINE, { $match, $group });
useOperators(OperatorType.ACCUMULATOR, { $min });

let agg = new Aggregator([
  { $match: { type: "homework" } },
  { $group: { _id: "$student_id", score: { $min: "$score" } } },
  { $sort: { _id: 1, score: 1 } },
]);

// return an iterator for streaming results
let stream = agg.stream(collection);

// return all results. same as `stream.all()`
let result = agg.run(collection);

Options

Query and aggregation operations can be configured with options to enabled different features or customize how documents are processed. Some options are only relevant to specific operators and need not be specified if not required.

interface Options {
  /** The key that is used to lookup the ID value of a document. @default "_id" */
  readonly idKey?: string;
  /** The collation specification for string operations. */
  readonly collation?: CollationSpec;
  /** Processing mode that determines how to treat inputs and outputs. @default ProcessingMode.CLONE_OFF */
  readonly processingMode?: ProcessingMode;
  /**
   * Enables or disables custom script execution.
   * When disabled, you cannot use operations that execute custom code, such as the $where, $accumulator, and $function.
   * @default true
   */
  readonly scriptEnabled?: boolean;
  /** Hash function to replace the somewhat weaker default implementation. */
  readonly hashFunction?: HashFunction;
  /** Function to resolve string reference to a collection for use by `$lookup` and `$out` operators. */
  readonly collectionResolver?: CollectionResolver;
  /** JSON schema validator to use with the $jsonSchema operator. Required to use the operator. */
  readonly jsonSchemaValidator?: JsonSchemaValidator;
}

Differences from MongoDB

  1. There is no concept of a collection. Input data is either an array of objects or a generator function to support streaming.
  2. Server-side specific operators are not supported. E.g. $collStat, $planCacheStats, $listSessions.
  3. Pipeline operator $merge is supported and enforces the unique constraint on the lookup field at runtime.
  4. The following operators are not supported.
    • Query: $comment, $meta, $text
    • Expression: $toObjectId, $binarySize, bsonSize
  5. The collectionResolver option can be configured to reference an array using a name for lookup instead of providing the reference directly. This is used in $lookup, $out, merge, and $unionWith.
  6. Custom function evaluation operators $where, $function, and $accumulator do not accept strings as the function body.
  7. Custom function evaluation operators are enabled by default. They can be disabled with the scriptEnabled option.
  8. $accumulator does not support the merge option.

Benefits

  • Better alternative to writing custom code for transforming collection of objects
  • Quick validation of MongoDB queries without the need for a database
  • MongoDB query language is among the best in the market and is well documented

Contributing

  • Squash changes into one commit
  • Run npm test to build and execute unit tests
  • Submit pull request

License

MIT

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100
Gervwyk29 Ratings0 Reviews
Co-Founder of Lowdefy gvw@lowdefy.com
5 months ago

Alternatives

No alternatives found

Tutorials

No tutorials found
Add a tutorial