Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lookup example please #150

Closed
billreynolds007 opened this issue Aug 24, 2020 · 5 comments
Closed

Lookup example please #150

billreynolds007 opened this issue Aug 24, 2020 · 5 comments

Comments

@billreynolds007
Copy link

I have reviewed the issues related to $lookup and have not found a full example of its use. I am confused as to how to reference the secondary collection being "looked into" with the various Mingo API functions which are passed a single collection.
Any help would be greatly appreciated.
Thank you,

@kofrasa
Copy link
Owner

kofrasa commented Aug 26, 2020

Hi @billreynolds007, so the documentation for this library is thin as it mostly relies on the public MongoDB docs. That is deliberate but it fails for operators such as$lookup, that is not compatible due to the different environments.

For mingo, $lookup requires the from argument to be an Array of objects instead of a String like in MongoDB. mingo does
not manage collections so any argument referring to a collection in MongoDB, must in this library be the actual collection of objects. The same applies to operators such as $out

I will try to expand on the API docs for such edge cases.

@billreynolds007
Copy link
Author

billreynolds007 commented Aug 26, 2020

Thank you @kofrasa. I have put together something for you to consider down the road to allow a hook to retrieve a referenced collection on the fly when only its name is provided. I adjusted .\mingo\operators\pipeline\lookup.js as shown below

function $lookup(collection, expr, options) {
    var joinColl = expr.from;
    // <--- Start hook to lookup collection on the fly
    if ( (typeof joinColl === 'string') && (typeof globalCollectionResolver !== 'undefined') )
      {
      console.log('LOOKUP', expr, options);
      joinColl = globalCollectionResolver.resolve(joinColl);
      console.log('resolved joinColl', joinColl);
      }
    // End hook --->
   ...

Here is my proof of concept node application,

const mingo = require('mingo')
var { Aggregator } = require('mingo/aggregator')
var { useOperators, OperatorType } = require('mingo/core')
var { $match, $lookup } = require('mingo/operators/pipeline')
useOperators(OperatorType.PIPELINE, { $match, $lookup })
var doc = { who: 'johnny', score: 75, type: 'homework' };
var docs = [doc];
var students = [ {nickName: 'johnny', first: 'John', last: 'Doe'} ];
// Install our Mingo resolver
global.globalCollectionResolver = {
  resolve:  function(collectionName)
     {
     // TODO Actually look at collectionName!
     return students; // Demo purposes
     }
  };
let agg = new Aggregator([
  {'$match': { "type": "homework"}},
  {'$lookup': { 
        from: 'students', // The STRING!
        localField: "who",
        foreignField: "nickName",
        as: "profile"
	}},
])
let result = agg.run(docs)
console.log( JSON.stringify(result, null, 2) );

The resulting output is shown below,

LOOKUP {
  from: 'students',
  localField: 'who',
  foreignField: 'nickName',
  as: 'profile'
} { config: { idKey: '_id' } }
resolved joinColl [ { nickName: 'johnny', first: 'John', last: 'Doe' } ]
[
  {
    "who": "johnny",
    "score": 75,
    "type": "homework",
    "profile": [
      {
        "nickName": "johnny",
        "first": "John",
        "last": "Doe"
      }
    ]
  }
]

This pattern could be used anywhere there is currently a collection argument.

Thanks again for all the work on Mingo. It's been awhile since I look at the internals last year when I put together the collating proof of concept example. The community and I appreciate you evolving that into Mingo.

  • Bill

@kofrasa
Copy link
Owner

kofrasa commented Aug 27, 2020

Thanks for the suggestion Bill. I like the design and I think it could work.

I would opt for a local resolver though, so that it can be passed through the options. With that, users are free to assign different options to the global space and use as desired. Mingo switched to local options since 3.0.0 to prevent conflicts between different libraries using it in the same project.

A single function say, resolveCollection on the options object could do it. While we let the idea simmer a bit, feel free to send a PR for reference.

Thanks again for raising this up and for your continued contribution to this library.

@billreynolds007
Copy link
Author

Hi @kofrasa. I would suggest you support both flavors of interaction:

  1. a well known global (with a better and distint Mingo-like name)
  2. an options element within the $lookup call

Each has tradeoffs that the developer can decide upon to fit his or her requirements.
The first option enables the same query to run in both MongoDB and Mingo worlds.
There is no extra options argument to pass in. It looks and feels like regular MongoDB
at the query level.

I do like the options approach you suggested and the flexibility that offers. This would be
first in line to perform any collection name resolution, with the fallback the global resolver (if any).

  • Bill

@kofrasa
Copy link
Owner

kofrasa commented Jan 7, 2021

Fixed in 4.0.0

@kofrasa kofrasa closed this as completed Jan 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants