MongoDB query language for in-memory objects
$ npm install mingo
<array>.<index>
and <document>.<field>
selectors$$ROOT
, $$CURRENT
, $$DESCEND
, $$PRUNE
, $$KEEP
, $$REMOVE
, $$NOW
For documentation on using query operators see mongodb
Browse package docs for modules.
// Use as es6 module
import mingo from "mingo";
// or vanilla nodeJS
const mingo = require("mingo");
The main module exports Aggregator
, Query
, aggregate()
, find()
, and remove()
. Only Query and Projection operators are loaded by default when you require the main module. This is done using the side-effect module mingo/init/basic
and automatically includes pipeline operators; $project
, $skip
, $limit
, and $sort
.
MongoDB query library is huge and you may not need all the operators. If using this library on the server-side where bundle size is not a concern, 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
To support tree-shaking for client side bundles, you can import and register specific operators that will be used in your application.
import { useOperators, OperatorType } from "mingo/core";
import { $trunc } from "mingo/operators/expression/trunc";
import { $bucket } from "mingo/operators/pipeline/bucket";
useOperators(OperatorType.EXPRESSION, { $trunc });
useOperators(OperatorType.PIPELINE, { $bucket });
const core = require("mingo/core");
const $trunc = require("mingo/operators/expression/trunc").$trunc;
const $bucket = require("mingo/operators/pipeline/bucket").$bucket;
const useOperators = core.useOperators;
const OperatorType = core.OperatorType;
useOperators(OperatorType.EXPRESSION, { $trunc: $trunc });
useOperators(OperatorType.PIPELINE, { $bucket: $bucket });
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);
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();
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.
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);
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 sorting operations. */
readonly collation?: CollationSpec;
/** Determines how to treat inputs and outputs. @default ProcessingMode.CLONE_OFF */
readonly processingMode?: ProcessingMode;
/**
* Enforces strict MongoDB compatibilty. See readme for differences. @default true.
* When disabled, the $elemMatch projection operator returns all matching nested documents instead of only the first.
*/
readonly useStrictMode?: boolean;
/**
* 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 strings to arrays for use with operators that reference other collections such as; `$lookup`, `$out` and `$merge`. */
readonly collectionResolver?: CollectionResolver;
/** JSON schema validator to use with the '$jsonSchema' operator. This is required in order to use the operator. */
readonly jsonSchemaValidator?: JsonSchemaValidator;
/** Global variables. */
readonly variables?: Readonly<RawObject>;
}
Custom operators can be added with the useOperators(type, operatorMap) where
type
is the kind of operators to add, and operatorMap
is mapping of function names beginning with $
to their implementations for the specific operator type.
Once an operator has been registered the function referenced cannot be replaced. This ensures that behaviour of mingo
remain consistent at runtime.
Each operator type function has a different signature and must be registered correctly otherwise the result will be unexpected.
Pre-loaded operators defined here cannot be overridden. These include;
$project
, $skip
, $limit
, and $sort
.$collStat
, $planCacheStats
, $listSessions
.$comment
, $meta
, $text
.$toObjectId
, $binarySize
, bsonSize
.$merge
enforces unique constraint on the lookup field at runtime.$where
, $function
, and $accumulator
, do not accept strings as the function body.scriptEnabled
option.merge
option.$jsonSchema
operator requires the user to register their own validator using the jsonSchemaValidator
option.npm test
to build and execute unit testsTo validate correct behaviour and semantics of operators, you may also test against mongoplayground.net.
MIT
Generated using TypeDoc