From 5393a2b00127f64b421ddb1c3db3141435475170 Mon Sep 17 00:00:00 2001 From: Kamil Dziedzic Date: Thu, 31 Aug 2017 13:52:37 +0200 Subject: [PATCH] PMM-685: explain --- .travis.yml | 22 ++- src/go/lib/tutil/util.go | 3 +- src/go/mongolib/explain/explain.go | 32 ++++ src/go/mongolib/explain/explain_test.go | 159 ++++++++++++++++++ .../fingerprinter/fingerprinter_test.go | 5 + src/go/mongolib/profiler/profiler_test.go | 8 +- src/go/mongolib/proto/bson.go | 25 ++- src/go/mongolib/proto/system.profile.go | 142 ++++++++++++++++ src/go/mongolib/stats/stats.go | 13 +- src/go/mongolib/stats/stats_test.go | 2 +- src/go/tests/doc/out/delete_all_2.6.12 | 33 ++++ src/go/tests/doc/out/delete_all_3.0.15 | 47 ++++++ src/go/tests/doc/out/delete_all_3.2.16 | 42 +++++ src/go/tests/doc/out/delete_all_3.4.7 | 113 +++++++++++++ src/go/tests/doc/out/delete_all_3.5.11 | 116 +++++++++++++ src/go/tests/doc/script/profile/delete_all.js | 9 + src/go/tests/profiler_docs_stats.want.json | 6 +- 17 files changed, 751 insertions(+), 26 deletions(-) create mode 100644 src/go/mongolib/explain/explain.go create mode 100644 src/go/mongolib/explain/explain_test.go create mode 100644 src/go/tests/doc/out/delete_all_2.6.12 create mode 100644 src/go/tests/doc/out/delete_all_3.0.15 create mode 100644 src/go/tests/doc/out/delete_all_3.2.16 create mode 100644 src/go/tests/doc/out/delete_all_3.4.7 create mode 100644 src/go/tests/doc/out/delete_all_3.5.11 create mode 100644 src/go/tests/doc/script/profile/delete_all.js diff --git a/.travis.yml b/.travis.yml index 68c7d62f..6e16fcf2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,21 @@ language: go go: - 1.8.x - - tip + +services: + - docker + +env: + matrix: + - MONGODB_IMAGE=mongo:3.2 + - MONGODB_IMAGE=mongo:3.4 + - MONGODB_IMAGE=percona/percona-server-mongodb:3.2 + - MONGODB_IMAGE=percona/percona-server-mongodb:3.4 + +matrix: + include: + - go: tip + env: install: - go get -u github.com/Masterminds/glide @@ -16,6 +30,12 @@ install: before_script: # check if vendor dir is correct - git diff --exit-code + # run docker containers + - docker-compose up -d + # log versions + - docker --version + - docker-compose --version + - docker-compose exec mongo mongo --version script: - go test -timeout 1m $(glide nv) diff --git a/src/go/lib/tutil/util.go b/src/go/lib/tutil/util.go index 9bd2477f..5cbf9cad 100644 --- a/src/go/lib/tutil/util.go +++ b/src/go/lib/tutil/util.go @@ -5,9 +5,8 @@ import ( "io/ioutil" "os" "os/exec" - "strings" - "regexp" + "strings" "gopkg.in/mgo.v2/bson" ) diff --git a/src/go/mongolib/explain/explain.go b/src/go/mongolib/explain/explain.go new file mode 100644 index 00000000..8e58d0e1 --- /dev/null +++ b/src/go/mongolib/explain/explain.go @@ -0,0 +1,32 @@ +package explain + +import ( + "github.com/percona/percona-toolkit/src/go/mongolib/proto" + "github.com/percona/pmgo" + "gopkg.in/mgo.v2/bson" +) + +type explain struct { + session pmgo.SessionManager +} + +func New(session pmgo.SessionManager) *explain { + return &explain{ + session: session, + } +} + +func (e *explain) Explain(eq proto.ExampleQuery) ([]byte, error) { + var result proto.BsonD + err := e.session.DB(eq.Db()).Run(eq.ExplainCmd(), &result) + if err != nil { + return nil, err + } + + resultJson, err := bson.MarshalJSON(result) + if err != nil { + return nil, err + } + + return resultJson, nil +} diff --git a/src/go/mongolib/explain/explain_test.go b/src/go/mongolib/explain/explain_test.go new file mode 100644 index 00000000..ee0b8ad0 --- /dev/null +++ b/src/go/mongolib/explain/explain_test.go @@ -0,0 +1,159 @@ +package explain + +import ( + "io/ioutil" + "log" + "os" + "testing" + + "fmt" + + "github.com/percona/percona-toolkit/src/go/lib/tutil" + "github.com/percona/percona-toolkit/src/go/mongolib/proto" + "github.com/percona/pmgo" + "github.com/stretchr/testify/require" + "gopkg.in/mgo.v2/bson" +) + +const ( + samples = "/src/go/tests/" +) + +type testVars struct { + RootPath string +} + +var vars testVars + +func TestMain(m *testing.M) { + var err error + if vars.RootPath, err = tutil.RootPath(); err != nil { + log.Printf("cannot get root path: %s", err.Error()) + os.Exit(1) + } + os.Exit(m.Run()) +} + +func TestExplain(t *testing.T) { + t.Parallel() + + dir := vars.RootPath + samples + "/doc/out/" + files, err := ioutil.ReadDir(dir) + if err != nil { + t.Fatalf("cannot list samples: %s", err) + } + + expectError := map[string]string{ + "aggregate_2.6.12": "Cannot explain cmd: aggregate", + "aggregate_3.0.15": "Cannot explain cmd: aggregate", + "aggregate_3.2.16": "Cannot explain cmd: aggregate", + "aggregate_3.4.7": "Cannot explain cmd: aggregate", + "aggregate_3.5.11": "Cannot explain cmd: aggregate", + "count_2.6.12": "", + "count_3.0.15": "", + "count_3.2.16": "", + "count_3.4.7": "", + "count_3.5.11": "", + "count_with_query_2.6.12": "", + "count_with_query_3.0.15": "", + "count_with_query_3.2.16": "", + "count_with_query_3.4.7": "", + "count_with_query_3.5.11": "", + "delete_2.6.12": "", + "delete_3.0.15": "", + "delete_3.2.16": "", + "delete_3.4.7": "", + "delete_3.5.11": "", + "delete_all_2.6.12": "", + "delete_all_3.0.15": "", + "delete_all_3.2.16": "", + "delete_all_3.4.7": "", + "delete_all_3.5.11": "", + "distinct_2.6.12": "", + "distinct_3.0.15": "", + "distinct_3.2.16": "", + "distinct_3.4.7": "", + "distinct_3.5.11": "", + "find_empty_2.6.12": "", + "find_empty_3.0.15": "", + "find_empty_3.2.16": "", + "find_empty_3.4.7": "", + "find_empty_3.5.11": "", + "find_2.6.12": "", + "find_3.0.15": "", + "find_3.2.16": "", + "find_3.4.7": "", + "find_3.5.11": "", + "find_andrii_2.6.12": "", + "find_andrii_3.0.15": "", + "find_andrii_3.2.16": "", + "find_andrii_3.4.7": "", + "find_andrii_3.5.11": "", + "findandmodify_2.6.12": "", + "findandmodify_3.0.15": "", + "findandmodify_3.2.16": "", + "findandmodify_3.4.7": "", + "findandmodify_3.5.11": "", + "geonear_2.6.12": "Cannot explain cmd: geoNear", + "geonear_3.0.15": "Cannot explain cmd: geoNear", + "geonear_3.2.16": "Cannot explain cmd: geoNear", + "geonear_3.4.7": "Cannot explain cmd: geoNear", + "geonear_3.5.11": "Cannot explain cmd: geoNear", + "group_2.6.12": "", + "group_3.0.15": "", + "group_3.2.16": "", + "group_3.4.7": "", + "group_3.5.11": "", + "insert_2.6.12": "Cannot explain cmd: insert", + "insert_3.0.15": "Cannot explain cmd: insert", + "insert_3.2.16": "Cannot explain cmd: insert", + "insert_3.4.7": "Cannot explain cmd: insert", + "insert_3.5.11": "Cannot explain cmd: insert", + "mapreduce_2.6.12": "Cannot explain cmd: mapReduce", + "mapreduce_3.0.15": "Cannot explain cmd: mapReduce", + "mapreduce_3.2.16": "Cannot explain cmd: mapReduce", + "mapreduce_3.4.7": "Cannot explain cmd: mapReduce", + "mapreduce_3.5.11": "Cannot explain cmd: mapReduce", + "update_2.6.12": "", + "update_3.0.15": "", + "update_3.2.16": "", + "update_3.4.7": "", + "update_3.5.11": "", + } + + dialer := pmgo.NewDialer() + dialInfo, err := pmgo.ParseURL("127.0.0.1:27017") + require.NoError(t, err) + + session, err := dialer.DialWithInfo(dialInfo) + require.NoError(t, err) + defer session.Close() + + ex := New(session) + + for _, file := range files { + t.Run(file.Name(), func(t *testing.T) { + eq := proto.ExampleQuery{} + err := tutil.LoadBson(dir+file.Name(), &eq) + if err != nil { + t.Fatalf("cannot load sample %s: %s", dir+file.Name(), err) + } + got, err := ex.Explain(eq) + expectErrMsg := expectError[file.Name()] + gotErrMsg := fmt.Sprintf("%v", err) + if gotErrMsg != expectErrMsg { + t.Fatalf("explain error should be '%s' but was '%s'", expectErrMsg, gotErrMsg) + } + + if err != nil { + return + } + + result := proto.BsonD{} + err = bson.UnmarshalJSON(got, &result) + if err != nil { + t.Fatalf("cannot unmarshal json explain result: %s", err) + } + }) + } +} diff --git a/src/go/mongolib/fingerprinter/fingerprinter_test.go b/src/go/mongolib/fingerprinter/fingerprinter_test.go index 836fc171..cbdb1d96 100644 --- a/src/go/mongolib/fingerprinter/fingerprinter_test.go +++ b/src/go/mongolib/fingerprinter/fingerprinter_test.go @@ -103,6 +103,11 @@ func TestFingerprints(t *testing.T) { "delete_3.2.16": "REMOVE coll a,b", "delete_3.4.7": "REMOVE coll a,b", "delete_3.5.11": "REMOVE coll a,b", + "delete_all_2.6.12": "REMOVE coll a,b", + "delete_all_3.0.15": "REMOVE coll a,b", + "delete_all_3.2.16": "REMOVE coll a,b", + "delete_all_3.4.7": "REMOVE coll a,b", + "delete_all_3.5.11": "REMOVE coll a,b", "distinct_2.6.12": "DISTINCT coll a,b", "distinct_3.0.15": "DISTINCT coll a,b", "distinct_3.2.16": "DISTINCT coll a,b", diff --git a/src/go/mongolib/profiler/profiler_test.go b/src/go/mongolib/profiler/profiler_test.go index 037f3ec5..ee8e564b 100644 --- a/src/go/mongolib/profiler/profiler_test.go +++ b/src/go/mongolib/profiler/profiler_test.go @@ -73,7 +73,7 @@ func TestRegularIterator(t *testing.T) { ID: "16196765fb4c14edb91efdbe4f5c5973", Namespace: "samples.col1", Operation: "query", - Query: "{\n \"find\": \"col1\",\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ]\n}", + Query: "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"shardVersion\":[0,\"000000000000000000000000\"]}}\n", Fingerprint: "FIND col1 find", FirstSeen: firstSeen, LastSeen: lastSeen, @@ -130,7 +130,7 @@ func TestIteratorTimeout(t *testing.T) { ID: "16196765fb4c14edb91efdbe4f5c5973", Namespace: "samples.col1", Operation: "query", - Query: "{\n \"find\": \"col1\",\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ]\n}", + Query: "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"shardVersion\":[0,\"000000000000000000000000\"]}}\n", Fingerprint: "FIND col1 find", FirstSeen: firstSeen, LastSeen: lastSeen, @@ -211,7 +211,7 @@ func TestTailIterator(t *testing.T) { ID: "16196765fb4c14edb91efdbe4f5c5973", Namespace: "samples.col1", Operation: "query", - Query: "{\n \"find\": \"col1\",\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ]\n}", + Query: "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"shardVersion\":[0,\"000000000000000000000000\"]}}\n", Fingerprint: "FIND col1 find", FirstSeen: parseDate("2017-04-01T23:01:20.214+00:00"), LastSeen: parseDate("2017-04-01T23:01:20.214+00:00"), @@ -226,7 +226,7 @@ func TestTailIterator(t *testing.T) { ID: "16196765fb4c14edb91efdbe4f5c5973", Namespace: "samples.col1", Operation: "query", - Query: "{\n \"find\": \"col1\",\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ]\n}", + Query: "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"shardVersion\":[0,\"000000000000000000000000\"]}}\n", Fingerprint: "FIND col1 find", FirstSeen: parseDate("2017-04-01T23:01:19.914+00:00"), LastSeen: parseDate("2017-04-01T23:01:19.914+00:00"), diff --git a/src/go/mongolib/proto/bson.go b/src/go/mongolib/proto/bson.go index d6a01bbf..b8664a72 100644 --- a/src/go/mongolib/proto/bson.go +++ b/src/go/mongolib/proto/bson.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "math" "gopkg.in/mgo.v2/bson" ) @@ -97,17 +98,31 @@ func (d BsonD) MarshalJSON() ([]byte, error) { } // marshal key - key, err := json.Marshal(v.Name) + key, err := bson.MarshalJSON(v.Name) if err != nil { return nil, err } b.Write(key) b.WriteByte(':') - // marshal value - val, err := json.Marshal(v.Value) - if err != nil { - return nil, err + var val []byte + if value, ok := v.Value.(float64); ok && math.IsInf(value, 0) { + if math.IsInf(value, 1) { + val = []byte("Infinity") + } else { + val = []byte("-Infinity") + } + + // below is wrong, but I'm later unable to Unmarshal Infinity, + // so we turn it into string for now + val = append([]byte(`"`), val...) + val = append(val, '"') + } else { + // marshal value + val, err = bson.MarshalJSON(v.Value) + if err != nil { + return nil, err + } } b.Write(val) } diff --git a/src/go/mongolib/proto/system.profile.go b/src/go/mongolib/proto/system.profile.go index bb444e9b..df4013d5 100644 --- a/src/go/mongolib/proto/system.profile.go +++ b/src/go/mongolib/proto/system.profile.go @@ -1,7 +1,10 @@ package proto import ( + "strings" "time" + + "gopkg.in/mgo.v2/bson" ) type SystemProfile struct { @@ -74,9 +77,148 @@ type SystemProfile struct { Op string `bson:"op"` Protocol string `bson:"protocol"` Query BsonD `bson:"query"` + UpdateObj BsonD `bson:"updateobj"` Command BsonD `bson:"command"` ResponseLength int `bson:"responseLength"` Ts time.Time `bson:"ts"` User string `bson:"user"` WriteConflicts int `bson:"writeConflicts"` } + +func NewExampleQuery(doc SystemProfile) ExampleQuery { + return ExampleQuery{ + Ns: doc.Ns, + Op: doc.Op, + Query: doc.Query, + Command: doc.Command, + UpdateObj: doc.UpdateObj, + } +} + +// ExampleQuery is a subset of SystemProfile +type ExampleQuery struct { + Ns string `bson:"ns" json:"ns"` + Op string `bson:"op" json:"op"` + Query BsonD `bson:"query,omitempty" json:"query,omitempty"` + Command BsonD `bson:"command,omitempty" json:"command,omitempty"` + UpdateObj BsonD `bson:"updateobj,omitempty" json:"updateobj,omitempty"` +} + +func (self ExampleQuery) Db() string { + ns := strings.SplitN(self.Ns, ".", 2) + if len(ns) > 0 { + return ns[0] + } + return "" +} + +func (self ExampleQuery) ExplainCmd() bson.D { + cmd := self.Command + + switch self.Op { + case "query": + if cmd.Len() == 0 { + cmd = self.Query + } + if cmd.Len() == 0 || cmd[0].Name != "find" { + var filter interface{} + if cmd.Len() > 0 && cmd[0].Name == "query" { + filter = cmd[0].Value + } else { + filter = cmd + } + + coll := "" + s := strings.SplitN(self.Ns, ".", 2) + if len(s) == 2 { + coll = s[1] + } + + cmd = BsonD{ + {"find", coll}, + {"filter", filter}, + } + } + case "update": + s := strings.SplitN(self.Ns, ".", 2) + coll := "" + if len(s) == 2 { + coll = s[1] + } + if cmd.Len() == 0 { + cmd = BsonD{ + {Name: "q", Value: self.Query}, + {Name: "u", Value: self.UpdateObj}, + } + } + cmd = BsonD{ + {Name: "update", Value: coll}, + {Name: "updates", Value: []interface{}{cmd}}, + } + case "remove": + s := strings.SplitN(self.Ns, ".", 2) + coll := "" + if len(s) == 2 { + coll = s[1] + } + if cmd.Len() == 0 { + cmd = BsonD{ + {Name: "q", Value: self.Query}, + // we can't determine if limit was 1 or 0 so we assume 0 + {Name: "limit", Value: 0}, + } + } + cmd = BsonD{ + {Name: "delete", Value: coll}, + {Name: "deletes", Value: []interface{}{cmd}}, + } + case "insert": + if cmd.Len() == 0 { + cmd = self.Query + } + if cmd.Len() == 0 || cmd[0].Name != "insert" { + coll := "" + s := strings.SplitN(self.Ns, ".", 2) + if len(s) == 2 { + coll = s[1] + } + + cmd = BsonD{ + {"insert", coll}, + } + } + case "command": + if cmd.Len() == 0 || cmd[0].Name != "group" { + break + } + + if v, ok := cmd[0].Value.(BsonD); ok { + for i := range v { + // for MongoDB <= 3.2 + // "$reduce" : function () {} + // It is then Unmarshaled as empty value, so in essence not working + // + // for MongoDB >= 3.4 + // "$reduce" : { + // "code" : "function () {}" + // } + // It is then properly Unmarshaled but then explain fails with "not code" + // + // The $reduce function shouldn't affect explain execution plan (e.g. what indexes are picked) + // so we ignore it for now until we find better way to handle this issue + if v[i].Name == "$reduce" { + v[i].Value = "" + cmd[0].Value = v + break + } + } + } + } + + return bson.D{ + { + Name: "explain", + Value: cmd, + }, + } +} diff --git a/src/go/mongolib/stats/stats.go b/src/go/mongolib/stats/stats.go index e8caaca9..5bb7098b 100644 --- a/src/go/mongolib/stats/stats.go +++ b/src/go/mongolib/stats/stats.go @@ -6,11 +6,11 @@ import ( "sort" "sync" "time" - "encoding/json" "github.com/montanaflynn/stats" "github.com/percona/percona-toolkit/src/go/mongolib/fingerprinter" "github.com/percona/percona-toolkit/src/go/mongolib/proto" + "gopkg.in/mgo.v2/bson" ) type StatsError struct { @@ -30,7 +30,6 @@ func (e *StatsError) Parent() error { } type StatsFingerprintError StatsError -type StatsGetQueryFieldError StatsError // New creates new instance of stats with given fingerprinter func New(fingerprinter fingerprinter.Fingerprinter) *Stats { @@ -75,14 +74,8 @@ func (s *Stats) Add(doc proto.SystemProfile) error { Namespace: doc.Ns, } if qiac, ok = s.getQueryInfoAndCounters(key); !ok { - query := doc.Query - if doc.Command.Len() > 0 { - query = doc.Command - } - if err != nil { - return &StatsGetQueryFieldError{err} - } - queryBson, err := json.MarshalIndent(query, "", " ") + query := proto.NewExampleQuery(doc) + queryBson, err := bson.MarshalJSON(query) if err != nil { return err } diff --git a/src/go/mongolib/stats/stats_test.go b/src/go/mongolib/stats/stats_test.go index 47a9b3a9..88f9eefc 100644 --- a/src/go/mongolib/stats/stats_test.go +++ b/src/go/mongolib/stats/stats_test.go @@ -142,7 +142,7 @@ func TestStats(t *testing.T) { ID: "4e4774ad26f934a193757002a991ebb8", Namespace: "samples.col1", Operation: "query", - Query: "{\n \"find\": \"col1\",\n \"filter\": {\n \"s2\": {\n \"$gte\": \"41991\",\n \"$lt\": \"33754\"\n }\n },\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ]\n}", + Query: "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"filter\":{\"s2\":{\"$gte\":\"41991\",\"$lt\":\"33754\"}},\"shardVersion\":[0,\"000000000000000000000000\"]}}\n", Fingerprint: "FIND col1 s2", FirstSeen: parseDate("2017-04-10T13:15:53.532-03:00"), LastSeen: parseDate("2017-04-10T13:15:53.532-03:00"), diff --git a/src/go/tests/doc/out/delete_all_2.6.12 b/src/go/tests/doc/out/delete_all_2.6.12 new file mode 100644 index 00000000..66995bb7 --- /dev/null +++ b/src/go/tests/doc/out/delete_all_2.6.12 @@ -0,0 +1,33 @@ +{ + "op" : "remove", + "ns" : "test.coll", + "query" : { + "a" : { + "$gte" : 2 + }, + "b" : { + "$gte" : 2 + } + }, + "ndeleted" : 15, + "keyUpdates" : 0, + "numYield" : 0, + "lockStats" : { + "timeLockedMicros" : { + "r" : NumberLong(0), + "w" : NumberLong(238) + }, + "timeAcquiringMicros" : { + "r" : NumberLong(0), + "w" : NumberLong(4) + } + }, + "millis" : 0, + "execStats" : { + + }, + "ts" : ISODate("2017-08-30T10:54:45.348Z"), + "client" : "127.0.0.1", + "allUsers" : [ ], + "user" : "" +} diff --git a/src/go/tests/doc/out/delete_all_3.0.15 b/src/go/tests/doc/out/delete_all_3.0.15 new file mode 100644 index 00000000..78f5d10b --- /dev/null +++ b/src/go/tests/doc/out/delete_all_3.0.15 @@ -0,0 +1,47 @@ +{ + "op" : "remove", + "ns" : "test.coll", + "query" : { + "a" : { + "$gte" : 2 + }, + "b" : { + "$gte" : 2 + } + }, + "ndeleted" : 15, + "keyUpdates" : 0, + "writeConflicts" : 0, + "numYield" : 0, + "locks" : { + "Global" : { + "acquireCount" : { + "r" : NumberLong(1), + "w" : NumberLong(1) + } + }, + "MMAPV1Journal" : { + "acquireCount" : { + "w" : NumberLong(16) + } + }, + "Database" : { + "acquireCount" : { + "w" : NumberLong(1) + } + }, + "Collection" : { + "acquireCount" : { + "W" : NumberLong(1) + } + } + }, + "millis" : 1, + "execStats" : { + + }, + "ts" : ISODate("2017-08-30T10:54:52.821Z"), + "client" : "127.0.0.1", + "allUsers" : [ ], + "user" : "" +} diff --git a/src/go/tests/doc/out/delete_all_3.2.16 b/src/go/tests/doc/out/delete_all_3.2.16 new file mode 100644 index 00000000..338c92c9 --- /dev/null +++ b/src/go/tests/doc/out/delete_all_3.2.16 @@ -0,0 +1,42 @@ +{ + "op" : "remove", + "ns" : "test.coll", + "query" : { + "a" : { + "$gte" : 2 + }, + "b" : { + "$gte" : 2 + } + }, + "ndeleted" : 15, + "keyUpdates" : 0, + "writeConflicts" : 0, + "numYield" : 0, + "locks" : { + "Global" : { + "acquireCount" : { + "r" : NumberLong(1), + "w" : NumberLong(1) + } + }, + "Database" : { + "acquireCount" : { + "w" : NumberLong(1) + } + }, + "Collection" : { + "acquireCount" : { + "w" : NumberLong(1) + } + } + }, + "millis" : 0, + "execStats" : { + + }, + "ts" : ISODate("2017-08-30T10:55:02.238Z"), + "client" : "127.0.0.1", + "allUsers" : [ ], + "user" : "" +} diff --git a/src/go/tests/doc/out/delete_all_3.4.7 b/src/go/tests/doc/out/delete_all_3.4.7 new file mode 100644 index 00000000..741b0c30 --- /dev/null +++ b/src/go/tests/doc/out/delete_all_3.4.7 @@ -0,0 +1,113 @@ +{ + "op" : "remove", + "ns" : "test.coll", + "query" : { + "a" : { + "$gte" : 2 + }, + "b" : { + "$gte" : 2 + } + }, + "keysExamined" : 39, + "docsExamined" : 39, + "ndeleted" : 15, + "keysDeleted" : 30, + "numYield" : 0, + "locks" : { + "Global" : { + "acquireCount" : { + "r" : NumberLong(1), + "w" : NumberLong(1) + } + }, + "Database" : { + "acquireCount" : { + "w" : NumberLong(1) + } + }, + "Collection" : { + "acquireCount" : { + "w" : NumberLong(1) + } + } + }, + "millis" : 0, + "planSummary" : "IXSCAN { a: 1 }", + "execStats" : { + "stage" : "DELETE", + "nReturned" : 0, + "executionTimeMillisEstimate" : 0, + "works" : 40, + "advanced" : 0, + "needTime" : 39, + "needYield" : 0, + "saveState" : 0, + "restoreState" : 0, + "isEOF" : 1, + "invalidates" : 0, + "nWouldDelete" : 15, + "nInvalidateSkips" : 0, + "inputStage" : { + "stage" : "FETCH", + "filter" : { + "b" : { + "$gte" : 2 + } + }, + "nReturned" : 15, + "executionTimeMillisEstimate" : 0, + "works" : 40, + "advanced" : 15, + "needTime" : 24, + "needYield" : 0, + "saveState" : 15, + "restoreState" : 15, + "isEOF" : 1, + "invalidates" : 0, + "docsExamined" : 39, + "alreadyHasObj" : 0, + "inputStage" : { + "stage" : "IXSCAN", + "nReturned" : 39, + "executionTimeMillisEstimate" : 0, + "works" : 40, + "advanced" : 39, + "needTime" : 0, + "needYield" : 0, + "saveState" : 15, + "restoreState" : 15, + "isEOF" : 1, + "invalidates" : 0, + "keyPattern" : { + "a" : 1 + }, + "indexName" : "a_1", + "isMultiKey" : false, + "multiKeyPaths" : { + "a" : [ ] + }, + "isUnique" : false, + "isSparse" : false, + "isPartial" : false, + "indexVersion" : 2, + "direction" : "forward", + "indexBounds" : { + "a" : [ + "[2.0, inf.0]" + ] + }, + "keysExamined" : 39, + "seeks" : 1, + "dupsTested" : 0, + "dupsDropped" : 0, + "seenInvalidated" : 0 + } + } + }, + "ts" : ISODate("2017-08-30T10:55:09.833Z"), + "client" : "127.0.0.1", + "appName" : "MongoDB Shell", + "allUsers" : [ ], + "user" : "" +} diff --git a/src/go/tests/doc/out/delete_all_3.5.11 b/src/go/tests/doc/out/delete_all_3.5.11 new file mode 100644 index 00000000..2435a88a --- /dev/null +++ b/src/go/tests/doc/out/delete_all_3.5.11 @@ -0,0 +1,116 @@ +{ + "op" : "remove", + "ns" : "test.coll", + "command" : { + "q" : { + "a" : { + "$gte" : 2 + }, + "b" : { + "$gte" : 2 + } + }, + "limit" : 0 + }, + "keysExamined" : 39, + "docsExamined" : 39, + "ndeleted" : 15, + "keysDeleted" : 30, + "numYield" : 0, + "locks" : { + "Global" : { + "acquireCount" : { + "r" : NumberLong(1), + "w" : NumberLong(1) + } + }, + "Database" : { + "acquireCount" : { + "w" : NumberLong(1) + } + }, + "Collection" : { + "acquireCount" : { + "w" : NumberLong(1) + } + } + }, + "millis" : 0, + "planSummary" : "IXSCAN { a: 1 }", + "execStats" : { + "stage" : "DELETE", + "nReturned" : 0, + "executionTimeMillisEstimate" : 0, + "works" : 40, + "advanced" : 0, + "needTime" : 39, + "needYield" : 0, + "saveState" : 0, + "restoreState" : 0, + "isEOF" : 1, + "invalidates" : 0, + "nWouldDelete" : 15, + "nInvalidateSkips" : 0, + "inputStage" : { + "stage" : "FETCH", + "filter" : { + "b" : { + "$gte" : 2 + } + }, + "nReturned" : 15, + "executionTimeMillisEstimate" : 0, + "works" : 40, + "advanced" : 15, + "needTime" : 24, + "needYield" : 0, + "saveState" : 15, + "restoreState" : 15, + "isEOF" : 1, + "invalidates" : 0, + "docsExamined" : 39, + "alreadyHasObj" : 0, + "inputStage" : { + "stage" : "IXSCAN", + "nReturned" : 39, + "executionTimeMillisEstimate" : 0, + "works" : 40, + "advanced" : 39, + "needTime" : 0, + "needYield" : 0, + "saveState" : 15, + "restoreState" : 15, + "isEOF" : 1, + "invalidates" : 0, + "keyPattern" : { + "a" : 1 + }, + "indexName" : "a_1", + "isMultiKey" : false, + "multiKeyPaths" : { + "a" : [ ] + }, + "isUnique" : false, + "isSparse" : false, + "isPartial" : false, + "indexVersion" : 2, + "direction" : "forward", + "indexBounds" : { + "a" : [ + "[2.0, inf.0]" + ] + }, + "keysExamined" : 39, + "seeks" : 1, + "dupsTested" : 0, + "dupsDropped" : 0, + "seenInvalidated" : 0 + } + } + }, + "ts" : ISODate("2017-08-30T10:55:19.142Z"), + "client" : "127.0.0.1", + "appName" : "MongoDB Shell", + "allUsers" : [ ], + "user" : "" +} diff --git a/src/go/tests/doc/script/profile/delete_all.js b/src/go/tests/doc/script/profile/delete_all.js new file mode 100644 index 00000000..d612bde4 --- /dev/null +++ b/src/go/tests/doc/script/profile/delete_all.js @@ -0,0 +1,9 @@ +var coll = db.coll + +for (i = 0; i < 10; ++i) { + coll.insert({a: i, b: i}); +} + +coll.createIndex({a: 1}); + +coll.remove({a: {$gte: 2}, b: {$gte: 2}}) diff --git a/src/go/tests/profiler_docs_stats.want.json b/src/go/tests/profiler_docs_stats.want.json index 34f8276d..c6bb1f85 100644 --- a/src/go/tests/profiler_docs_stats.want.json +++ b/src/go/tests/profiler_docs_stats.want.json @@ -3,7 +3,7 @@ "ID": "16196765fb4c14edb91efdbe4f5c5973", "Namespace": "samples.col1", "Operation": "query", - "Query": "{\n \"find\": \"col1\",\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ]\n}", + "Query": "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"shardVersion\":[0,\"000000000000000000000000\"]}}\n", "Fingerprint": "FIND col1 find", "FirstSeen": "2017-04-10T13:16:23.29-03:00", "LastSeen": "2017-04-10T13:16:23.29-03:00", @@ -56,7 +56,7 @@ "ID": "4e4774ad26f934a193757002a991ebb8", "Namespace": "samples.col1", "Operation": "query", - "Query": "{\n \"find\": \"col1\",\n \"filter\": {\n \"s2\": {\n \"$gte\": \"41991\",\n \"$lt\": \"33754\"\n }\n },\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ]\n}", + "Query": "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"filter\":{\"s2\":{\"$gte\":\"41991\",\"$lt\":\"33754\"}},\"shardVersion\":[0,\"000000000000000000000000\"]}}\n", "Fingerprint": "FIND col1 s2", "FirstSeen": "2017-04-10T13:15:53.532-03:00", "LastSeen": "2017-04-10T13:15:53.532-03:00", @@ -109,7 +109,7 @@ "ID": "8cb8666ace7e54767b4d3c4f61860cf9", "Namespace": "samples.col1", "Operation": "query", - "Query": "{\n \"find\": \"col1\",\n \"filter\": {\n \"user_id\": {\n \"$gte\": 3384024924,\n \"$lt\": 195092007\n }\n },\n \"projection\": {\n \"$sortKey\": {\n \"$meta\": \"sortKey\"\n }\n },\n \"shardVersion\": [\n 0,\n \"000000000000000000000000\"\n ],\n \"sort\": {\n \"user_id\": 1\n }\n}", + "Query": "{\"ns\":\"samples.col1\",\"op\":\"query\",\"query\":{\"find\":\"col1\",\"filter\":{\"user_id\":{\"$gte\":3.384024924e+09,\"$lt\":1.95092007e+08}},\"projection\":{\"$sortKey\":{\"$meta\":\"sortKey\"}},\"shardVersion\":[0,\"000000000000000000000000\"],\"sort\":{\"user_id\":1}}}\n", "Fingerprint": "FIND col1 user_id", "FirstSeen": "2017-04-10T13:15:53.524-03:00", "LastSeen": "2017-04-10T13:15:53.524-03:00",