void DocumentSourceLookUp::serializeToArray(std::vector<Value>& array, bool explain) const { MutableDocument output(DOC( getSourceName() << DOC("from" << _fromNs.coll() << "as" << _as.fullPath() << "localField" << _localField.fullPath() << "foreignField" << _foreignField.fullPath()))); if (explain) { if (_handlingUnwind) { const boost::optional<FieldPath> indexPath = _unwindSrc->indexPath(); output[getSourceName()]["unwinding"] = Value(DOC("preserveNullAndEmptyArrays" << _unwindSrc->preserveNullAndEmptyArrays() << "includeArrayIndex" << (indexPath ? Value(indexPath->fullPath()) : Value()))); } if (_matchSrc) { // Our output does not have to be parseable, so include a "matching" field with the // descended match expression. output[getSourceName()]["matching"] = Value(DocumentSourceMatch::descendMatchOnPath( _matchSrc->getMatchExpression(), _as.fullPath(), pExpCtx) ->getQuery()); } array.push_back(Value(output.freeze())); } else { array.push_back(Value(output.freeze())); if (_handlingUnwind) { _unwindSrc->serializeToArray(array); } if (_matchSrc) { // '_matchSrc' tracks the originally specified $match. We descend upon the $match in the // first call to getNext(), at which point we are confident that we no longer need to // serialize the $lookup again. _matchSrc->serializeToArray(array); } } }