Skip to content

Instantly share code, notes, and snippets.

@lawrencejones
Last active March 15, 2019 19:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lawrencejones/e1ff8a85e32af6ff9a0e to your computer and use it in GitHub Desktop.
Save lawrencejones/e1ff8a85e32af6ff9a0e to your computer and use it in GitHub Desktop.
Projection generator for mongodb
_ = require 'underscore'
# Given an array of elements ELEM and a matching KEY value,
# will build the apprpriate projection to generate sortable
# weights for a mongo aggregator.
#
# ELEM: An array of values upon which to match against KEY
# KEY: The document field key to match against
# I: Default 0, index into array at which to begin
#
# Will return formatted projections. Note that elems must
# contain at least two elements for the initial call, else
# only the initial I value will be returned.
buildProjection = (elems, key, i = 0) ->
return i if (elems.length - i) == 1
$cond:
if: { $eq: [ "$#{key}", elems[i] ] }
then: i
else: buildProjection elems, key, i+1
# Assuming we have a mongoose userSchema, with the standard
# schema paths defined on userSchema.paths, we can make use
# of that objects keys to prevent $project from masking fields
# and then build our weights againsts the email key.
#
# Example.
#
# exampleQuery 'lmj112@ic.ac.uk', 'amv1882@ic.ac.uk'
# => [User(lmj112), User(amv1882)]
#
# Calling exec() simply generates a promise.
exampleQuery = (emails...) ->
projection =
_.object ([k,1] for own k,v of userSchema.paths)
projection.weight = buildProjection(emails, 'email')
User.aggregate([
{ $match: email: $in: emails }
{ $project: projection }
{ $sort: weight: 1 }
]).exec()
users = ['lmj112', 'amv1882', 'thb12']
console.log(JSON.stringify (buildProjection users, 'login'), undefined, 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment