func (qe *QueryExplainer) GetSummary(summary ExplainSummary) string {
	var buffer bytes.Buffer
	buffer.WriteString("\n")
	if summary.ShardName == "" {
		buffer.WriteString("Cluster: Replica Set\n")
	} else {
		buffer.WriteString("Cluster: Sharded, evaluated from shard " + summary.ShardName + "\n")
	}
	b, _ := bson.Marshal(qe.ExplainCmd)
	var qshape bson.M
	bson.Unmarshal(b, &qshape)
	delete(qshape, "find")
	buffer.WriteString("Query Shape:\n" + gox.Stringify(qshape, "", "  ") + "\n")
	buffer.WriteString("\n=> Execution Stats\n")
	buffer.WriteString("=========================================\n")
	buffer.WriteString("Winning Plan:\n")
	buffer.WriteString(getStageStatsSummaryString(summary.ExecutionStats, 1))
	if len(summary.AllPlansExecutionStats) > 0 {
		buffer.WriteString("\n=> All Plans Execution\n")
		buffer.WriteString("=========================================\n")
		sort.Slice(summary.AllPlansExecutionStats, func(i, j int) bool {
			return summary.AllPlansExecutionStats[i].Score > summary.AllPlansExecutionStats[j].Score
		})
		for i, stats := range summary.AllPlansExecutionStats {
			buffer.WriteString(fmt.Sprintf("Query Plan %d:\n", i+1))
			buffer.WriteString(getStageStatsSummaryString(stats, 0))
			buffer.WriteString("\n")
		}
	}
	return buffer.String()
}
GetSummary get summary of explain executionStats
package mdb
import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"math"
	"reflect"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"
	"github.com/simagix/gox"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
)
type QueryExplainer struct {
	ExplainCmd ExplainCommand `bson:"explain"`
	NameSpace  string
	client     *mongo.Client
	document   bson.D
	isSharded  bool
	shardUsed  int
	verbose    bool
}
type ExplainCommand struct {
	Collection string `bson:"find"`
	Filter     bson.D `bson:"filter"`
	Sort       bson.D `bson:"sort,omitempty"`
	Hint       bson.D `bson:"hint,omitempty"`
	Group      string `bson:"group,omitempty"`
}
type inputStagesLevel struct {
	inputStages []bson.D
	level       int
}
type StageStats struct {
	Level             int
	Score             float64         `json:"Score"`
	Stage             string          `json:"stage"`
	Filter            *gox.OrderedMap `json:"filter"`
	KeyPattern        *gox.OrderedMap `json:"keyPattern"`
	Advanced          int32           `json:"advanced"`
	Works             int32           `json:"works"`
	ExecTimeMillisEst int32           `json:"executionTimeMillisEstimate"`
	TotalKeysExamined int32           `json:"totalKeysExamined"`
	TotalDocsExamined int32           `json:"totalDocsExamined"`
	InputStages       []StageStats    `json:"inputStages"`
}
type ExplainSummary struct {
	ShardName              string       `json:"shardName"`
	ExecutionStats         StageStats   `json:"executionStats"`
	AllPlansExecutionStats []StageStats `json:"allPlansExecution"`
}
type IndexScore struct {
	Index gox.OrderedMap `json:"index"`
	Score float64        `json:"score"`
}
func NewQueryExplainer(client *mongo.Client) *QueryExplainer {
	return &QueryExplainer{client: client, ExplainCmd: ExplainCommand{}}
}
func (qe *QueryExplainer) SetVerbose(verbose bool) {
	qe.verbose = verbose
}
func (qe *QueryExplainer) GetFilter() bson.D {
	return qe.ExplainCmd.Filter
}
func (qe *QueryExplainer) Explain() (ExplainSummary, error) {
	var err error
	var command bson.D
	o := QueryExplainer{}
	b, _ := bson.Marshal(qe)
	bson.Unmarshal(b, &o)
	o.ExplainCmd.Group = ""  
	b, _ = bson.Marshal(o)
	bson.Unmarshal(b, &command)
	db := strings.Split(qe.NameSpace, ".")[0]
	if err = qe.client.Database(db).RunCommand(context.Background(), command).Decode(&qe.document); err != nil {
		return ExplainSummary{}, err
	}
	doc := qe.document.Map()
	winStage := doc["queryPlanner"].(bson.D).Map()["winningPlan"].(bson.D).Map()["stage"].(string)
	if winStage == "EOF" {
		return ExplainSummary{}, errors.New("no data found to be explained")
	} else if winStage == "COLLSCAN" {
		return ExplainSummary{}, errors.New("no index selected (COLLSCAN)")
	}
	return qe.GetExplainDetails(doc), err
}
func (qe *QueryExplainer) GetExplainDetails(doc bson.M) ExplainSummary {
	summary := ExplainSummary{}
	winningPlan := doc["queryPlanner"].(bson.D).Map()["winningPlan"].(bson.D).Map()
	if winningPlan["shards"] != nil {
		qe.isSharded = true
	}
	summary.ExecutionStats = qe.getStageStats(doc["executionStats"].(bson.D))
	summary.AllPlansExecutionStats = []StageStats{}
	allPlansExecution := doc["executionStats"].(bson.D).Map()["allPlansExecution"].(primitive.A)
	if qe.isSharded && len(allPlansExecution) > 0 {
		maxReturned := int32(0)
		shardNames := []string{}
		for i, plansExecution := range allPlansExecution {
			shardNames = append(shardNames, plansExecution.(bson.D).Map()["shardName"].(string))
			allPlans := plansExecution.(bson.D).Map()["allPlans"].(primitive.A)
			for _, plan := range allPlans {
				rt := plan.(bson.D).Map()["nReturned"].(int32)
				if rt > maxReturned {
					maxReturned = rt
					qe.shardUsed = i
				}
			}
		}
		summary.ShardName = shardNames[qe.shardUsed]
		allPlansExecution = allPlansExecution[qe.shardUsed].(bson.D).Map()["allPlans"].(primitive.A)
	}
	for _, execution := range allPlansExecution {
		exec := execution.(bson.D)
		summary.AllPlansExecutionStats = append(summary.AllPlansExecutionStats, qe.getStageStats(exec))
	}
	return summary
}