@@ -518,29 +518,43 @@ BSONObj calculateFinalScore(
518
518
return BSON (" $addFields" << BSON (" score" << allInputs ()));
519
519
}
520
520
521
- BSONObj calculateFinalScoreDetails (
522
- const std::map<std::string, std::unique_ptr<Pipeline, PipelineDeleter>>& inputs) {
523
- // Generate the following string for each pipeline:
524
- // "name: {rank: $name_rank, details: $name_scoreDetails}""
525
- // And add them all to an array to be merged together.
526
- BSONObjBuilder bob;
527
- BSONArrayBuilder mergeNamedDetailsBob (bob.subarrayStart (" $mergeObjects" _sd));
528
- for (auto it = inputs.begin (); it != inputs.end (); it++) {
529
- mergeNamedDetailsBob.append (fromjson (
530
- fmt::format (" {{{0}: {{$mergeObjects: [{{rank: '${0}_rank'}}, '${0}_scoreDetails']}}}}" ,
531
- it->first )));
532
- }
533
- mergeNamedDetailsBob.done ();
521
+ boost::intrusive_ptr<DocumentSource> calculateFinalScoreDetails (
522
+ const std::map<std::string, std::unique_ptr<Pipeline, PipelineDeleter>>& inputs,
523
+ const boost::intrusive_ptr<ExpressionContext>& expCtx) {
534
524
// Create the following object:
535
525
/*
536
526
{ $addFields: {
537
527
calculatedScoreDetails: {
538
- $mergeObjects: [<generated above>]
528
+ $mergeObjects: [
529
+ name1: {
530
+ $mergeObjects: [{"rank" << "$name1_rank"}, "$name1_scoreDetails"]
531
+ },
532
+ name2: {
533
+ $mergeObjects: [{"rank" << "$name2_rank"}, "$name2_scoreDetails"]
534
+ },
535
+ ...
536
+ ]
539
537
}
540
538
}
541
539
*/
542
- return fromjson (
543
- fmt::format (" {{$addFields: {{calculatedScoreDetails: {0}}}}}" , bob.obj ().toString ()));
540
+ BSONObjBuilder bob;
541
+ BSONArrayBuilder topLevelMergeNamedDetailsBob (bob.subarrayStart (" $mergeObjects" _sd));
542
+ for (auto it = inputs.begin (); it != inputs.end (); it++) {
543
+ const std::string rankFieldName = fmt::format (" ${}_rank" , it->first );
544
+ const std::string scoreDetailsFieldName = fmt::format (" ${}_scoreDetails" , it->first );
545
+ topLevelMergeNamedDetailsBob.append (
546
+ BSON (it->first << BSON (" $mergeObjects" _sd << BSON_ARRAY (BSON (" rank" _sd << rankFieldName)
547
+ << scoreDetailsFieldName))));
548
+ }
549
+ topLevelMergeNamedDetailsBob.done ();
550
+
551
+ boost::intrusive_ptr<Expression> mergeObjectsExpr =
552
+ ExpressionFromAccumulator<AccumulatorMergeObjects>::parse (
553
+ expCtx.get (), bob.obj ().firstElement (), expCtx->variablesParseState );
554
+
555
+ auto addFields = DocumentSourceAddFields::create (
556
+ " calculatedScoreDetails" _sd, std::move (mergeObjectsExpr), expCtx.get ());
557
+ return addFields;
544
558
}
545
559
546
560
boost::intrusive_ptr<DocumentSource> buildUnionWithPipeline (
@@ -589,8 +603,8 @@ std::list<boost::intrusive_ptr<DocumentSource>> buildScoreAndMergeStages(
589
603
SbeCompatibility::noRequirements);
590
604
591
605
if (includeScoreDetails) {
592
- auto addFieldsDetails = DocumentSourceAddFields::createFromBson (
593
- calculateFinalScoreDetails (inputPipelines). firstElement () , expCtx);
606
+ boost::intrusive_ptr<DocumentSource> addFieldsDetails =
607
+ calculateFinalScoreDetails (inputPipelines, expCtx);
594
608
auto setDetails = DocumentSourceSetMetadata::create (
595
609
expCtx,
596
610
Expression::parseObject (expCtx.get (),
0 commit comments