npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

feathers-mongodb-aggregate

v6.5.1

Published

Feathers MongoDB service - aggregate

Downloads

10

Readme

feathers-mongodb-aggregate

This is a fork from feathers-mongodb with option agregate on find and get

:wrench: WIP!!!

but kind of works

Before!

Check if fastjoin with batchLoader works for you.

Why

FeathersJs is great, but with MongoDB something like a lookup is very db intensive for multiple documents, since feathers-mongodb does not support aggregations I made some changes.

Just add an array (aggregate) to params

export default {
  before: {
    all: [
      authenticate('jwt'),
    ],
    find: [
      (context) => {
        context.params.aggregate = [
          {
            $lookup: {
              from: 'storage',
              localField: '_id',
              foreignField: 'productId',
              as: '_l_stock',
            },
          },
          {
            $set: {
              _l_stock: { $arrayElemAt: ['$_l_stock.currentStock', 0] },
            },
          },
        ]
        return context
      },
    ],

Some important notes:

You can use all that the MongoDb aggregate has to offer, but...

To use the native FeathersJS options I arrange the aggregate array like this:

somedb.aggregate(
  [
    {
      $match: {
        // FeathersJS query
        }
    },
    {
      // Your aggregate array!
      // Your aggregate array!
      // Your aggregate array!
    },
    {
      $project: {
        $select: // FeathersJS select
      }
    },
    
    {
      $sort: {
        // FeathersJS sort
      }
    },
    {
      $limit: // FeathersJS limit
    },
    {
      $skip: // FeathersJS skip
    }
]

Sample hook.

(not necessary)

TODO

  • Count / test

A Feathers database adapter for MongoDB using official NodeJS driver for MongoDB.

$ npm install --save mongodb feathers-mongodb

Important: feathers-mongodb implements the Feathers Common database adapter API and querying syntax.

This adapter also requires a running MongoDB database server.

API

service(options)

Returns a new service instance initialized with the given options. Model has to be a MongoDB collection.

const MongoClient = require('mongodb').MongoClient;
const service = require('feathers-mongodb-lookup');

MongoClient.connect('mongodb://localhost:27017/feathers').then(client => {
  app.use('/messages', service({
    Model: client.db('feathers').collection('messages')
  }));
  app.use('/messages', service({ Model, id, events, paginate }));
});

Options:

  • Model (required) - The MongoDB collection instance
  • id (optional, default: '_id') - The name of the id field property. By design, MongoDB will always add an _id property.
  • disableObjectify (optional, default false) - This will disable the objectify of the id field if you want to use normal strings
  • events (optional) - A list of custom service events sent by this service
  • paginate (optional) - A pagination object containing a default and max page size
  • whitelist (optional) - A list of additional query parameters to allow (e..g [ '$regex', '$geoNear' ])
  • multi (optional) - Allow create with arrays and update and remove with id null to change multiple items. Can be true for all methods or an array of allowed methods (e.g. [ 'remove', 'create' ])
  • useEstimatedDocumentCount (optional, default false) - If true document counting will rely on estimatedDocumentCount instead of countDocuments

params.mongodb

When making a service method call, params can contain an mongodb property (for example, {upsert: true}) which allows to modify the options used to run the MongoDB query.

Transactions

You can utilized a MongoDB Transactions by passing a session with the params.mongodb:

import { ObjectID } from 'mongodb'

export default async app => {
  app.use('/fooBarService', {
    async create(data) {
      // assumes you have access to the mongoClient via your app state
      let session = app.mongoClient.startSession()
      try {
        await session.withTransaction(async () => {
            let fooID = new ObjectID()
            let barID = new ObjectID()
            app.service('fooService').create(
              {
                ...data,
                _id: fooID,
                bar: barID,
              },
              { mongodb: { session } },
            )
            app.service('barService').create(
              {
                ...data,
                _id: barID
                foo: fooID
              },
              { mongodb: { session } },
            )
        })
      } finally {
        await session.endSession()
      }
    }
  })
}

Example

Here is an example of a Feathers server with a messages endpoint that writes to the feathers database and the messages collection.

$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express @feathersjs/socketio feathers-mongodb mongodb

In app.js:

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');

const MongoClient = require('mongodb').MongoClient;
const service = require('feathers-mongodb-lookup');

// Create an Express compatible Feathers application instance.
const app = express(feathers());
// Turn on JSON parser for REST services
app.use(express.json());
// Turn on URL-encoded parser for REST services
app.use(express.urlencoded({extended: true}));
// Enable REST services
app.configure(express.rest());
// Enable Socket.io
app.configure(socketio());

// Connect to the db, create and register a Feathers service.
app.use('/messages', service({
  paginate: {
    default: 2,
    max: 4
  }
}));

// A basic error handler, just like Express
app.use(express.errorHandler());

// Connect to your MongoDB instance(s)
MongoClient.connect('mongodb://localhost:27017/feathers')
  .then(function(client){
    // Set the model now that we are connected
    app.service('messages').Model = client.db('feathers').collection('messages');

    // Now that we are connected, create a dummy Message
    app.service('messages').create({
      text: 'Message created on server'
    }).then(message => console.log('Created message', message));
  }).catch(error => console.error(error));

// Start the server.
const port = 3030;

app.listen(port, () => {
  console.log(`Feathers server listening on port ${port}`);
});

Run the example with node app and go to localhost:3030/messages.

Querying

Additionally to the common querying mechanism this adapter also supports MongoDB's query syntax and the update method also supports MongoDB update operators.

Important: External query values through HTTP URLs may have to be converted to the same type stored in MongoDB in a before hook otherwise no matches will be found. Websocket requests will maintain the correct format if it is supported by JSON (ObjectIDs and dates still have to be converted).

For example, an age (which is a number) a hook like this can be used:

const ObjectID = require('mongodb').ObjectID;

app.service('users').hooks({
  before: {
    find(context) {
      const { query = {} } = context.params;

      if(query.age !== undefined) {
        query.age = parseInt(query.age, 10);
      }

      context.params.query = query;

      return Promise.resolve(context);
    }
  }
});

Which will allows queries like /users?_id=507f1f77bcf86cd799439011&age=25.

Collation Support

This adapter includes support for collation and case insensitive indexes available in MongoDB v3.4. Collation parameters may be passed using the special collation parameter to the find(), remove() and patch() methods.

Example: Patch records with case-insensitive alphabetical ordering

The example below would patch all student records with grades of 'c' or 'C' and above (a natural language ordering). Without collations this would not be as simple, since the comparison { $gt: 'c' } would not include uppercase grades of 'C' because the code point of 'C' is less than that of 'c'.

const patch = { shouldStudyMore: true };
const query = { grade: { $gte: 'c' } };
const collation = { locale: 'en', strength: 1 };
students.patch(null, patch, { query, collation }).then( ... );

Example: Find records with a case-insensitive search

Similar to the above example, this would find students with a grade of 'c' or greater, in a case-insensitive manner.

const query = { grade: { $gte: 'c' } };
const collation = { locale: 'en', strength: 1 };
students.find({ query, collation }).then( ... );

For more information on MongoDB's collation feature, visit the collation reference page.

License

Copyright (c) 2019

Licensed under the MIT license.