Morphia Aggregation Lookup syntax?

Viewed 140

I'm trying to achieve a join on three String fields between two collections on MongoDB v. 4.4.3: one containing the original documents, the other the translations. Both document types look like this:

{
   "_id" : ObjectId("60644367b521563be8044f07"),
   "dsId" : "2051918",
   "lcId" : "data_euscreenXL_EUS_15541BBE705033639D4E06691D7A5D2E",
   "pgId" : "1",
   (...)

This MongoDB query does what I need, embedding the Translations in the result:

db.Original.aggregate([
   {  $match: { query parameters } },
   {  $lookup:
     {
       from: "Translation",
       let: { "origDsId": "$dsId", origLcId: "$lcId", "origPgId": "$pgId" },
       pipeline: [
          { $match:
             { $expr:
                { $and:
                   [
                     { $eq: [ "$dsId",  "$$origDsId" ] },
                     { $eq: [ "$lcId",  "$$origLcId" ] },
                     { $eq: [ "$pgId",  "$$origPgId" ] }
                   ]
                }
             }
          },
          { $project: { dsId: 0, _id: 0 } }
       ],
       as: "translations"
     }
}])

However, I can't figure out how to write the equivalent Morphia query. I updated to Morphia v.2.2, which adds the required features, but it's all very new and hasn't yet been documented on morphia.dev; I couldn't find much more on Javadoc either. This Morphia unit test on Github looked interesting and I tried copying that approach:

Aggregation<Original> query = datastore.aggregate(Original.class)
           .match(eq("dsId", datasetId), eq("lcId", localId))
           .lookup(Lookup.lookup(Translation.class)
                   .let("origDsId", value("$dsId"))
                   .let("origLcId", value("$lcId"))
                   .let("origPgId", value("$pgId"))
           .pipeline(Match.match(expr(Expressions.of()
                   .field("$and",
                         array(Expressions
                              .of().field("$eq",
                                   array(field("dsId"),
                                         field("$origDsId"))),
                               Expressions
                              .of().field("$eq",
                                   array(field("lcId"),
                                         field("$origLcId"))),
                               Expressions
                              .of().field("$eq",
                                   array(field("pgId"),
                                         field("$origPgId"))))))))
                  .as("translations"));

... This returns the Original documents, but fails to join the Translations.

The problem is that the syntax of the pipeline stage is rather puzzling. I wonder if anyone can shed some light on this?

  • the unit test example does not use (or need?) the double-$ form seen in "$$origDsId"? From the MongoDB documentation I understand that this form is used to refer to externally defined variables (eg in the "let" assignment before the "pipeline") but they don't work in the quoted example either;
  • what is the role of the static ArrayExpression "array"? It looks as if it's a kind of assignment container, where Expressions.of().field("$eq", array(field("dsId"), field("$origDsId"))) might mean something like "dsId" = "$origDsId" - which would be what I need (if it would work ;) )
  • I tried all sorts of combinations, using field("$origDsId"), value("$origDsId"), field("$$origDsId"), value("$$origDsId"), etcetera, but having no luck so far.

Thanks in advance!

0 Answers
Related