-
Type:
Bug
-
Resolution: Done
-
Priority:
Major - P3
-
Affects Version/s: 2.5.4
-
Component/s: Querying, Text Search
-
None
-
ALL
-
None
-
None
-
None
-
None
-
None
-
None
-
None
The query planner selects the text index for queries targeting the prefix field of a compound text index. Since text indexes generate no index keys for documents without text data, results for these queries will omit documents with no indexed text data.
> db.foo.insert({a:17})
Insert WriteResult({ "ok" : 1, "n" : 1 })
> db.foo.ensureIndex({a:1,b:"text"})
> db.foo.count({a:17})
0
Explain output below:
> db.foo.find({a:17}).explain()
{
"cursor" : "BtreeCursor a_1_b_text",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 0,
"nscanned" : 0,
"nscannedObjectsAllPlans" : 0,
"nscannedAllPlans" : 0,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 1,
"indexBounds" : {
"a" : [
[
17,
17
]
],
"_fts" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"_ftsx" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "Rassi-MacBook-Pro.local:27017",
"stats" : {
"type" : "FETCH",
"works" : 1,
"yields" : 0,
"unyields" : 0,
"invalidates" : 0,
"advanced" : 0,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 0,
"children" : [
{
"type" : "IXSCAN",
"works" : 1,
"yields" : 0,
"unyields" : 0,
"invalidates" : 0,
"advanced" : 0,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"keyPattern" : "{ a: 1.0, _fts: \"text\", _ftsx: 1 }",
"bounds" : {
"a" : [
[
17,
17
]
],
"_fts" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"_ftsx" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"isMultiKey" : 0,
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 0,
"children" : [ ]
}
]
}
}
>
Verbose query log output below:
2014-01-22T20:56:33.476-0500 [conn1] Running query on new system: ns=test.foo limit=0 skip=0
Tree: a == 17.0
Sort: {}
Proj: {}
2014-01-22T20:56:33.476-0500 [conn1] =============================
Beginning planning, options = INCLUDE_COLLSCAN
Canonical query:
ns=test.foo limit=0 skip=0
Tree: a == 17.0
Sort: {}
Proj: {}
=============================
2014-01-22T20:56:33.476-0500 [conn1] idx 0 is kp: { _id: 1 } io: { v: 1, key: { _id: 1 }, name: "_id_", ns: "test.foo" }
2014-01-22T20:56:33.476-0500 [conn1] idx 1 is kp: { a: 1.0, _fts: "text", _ftsx: 1 } io: { v: 1, key: { a: 1.0, _fts: "text", _ftsx: 1 }, name: "a_1_b_text", ns: "test.foo", weights: { b: 1 }, default_language: "english", language_override: "language", textIndexVersion: 2 }
2014-01-22T20:56:33.476-0500 [conn1] predicate over field a
2014-01-22T20:56:33.476-0500 [conn1] relevant idx 0 is kp: { a: 1.0, _fts: "text", _ftsx: 1 } io: { v: 1, key: { a: 1.0, _fts: "text", _ftsx: 1 }, name: "a_1_b_text", ns: "test.foo", weights: { b: 1 }, default_language: "english", language_override: "language", textIndexVersion: 2 }
2014-01-22T20:56:33.476-0500 [conn1] rated tree
2014-01-22T20:56:33.476-0500 [conn1] a == 17.0 First: 0 notFirst: full path: a
2014-01-22T20:56:33.476-0500 [conn1] enumerator received root:
a == 17.0 First: 0 notFirst: full path: a
2014-01-22T20:56:33.476-0500 [conn1] Tagging memoID 0
2014-01-22T20:56:33.476-0500 [conn1] Enumerator: memo right before moving:
2014-01-22T20:56:33.476-0500 [conn1] [Node #0]: predicate, first indices: [0], pred: a == 17.0
indexToAssign: 0
2014-01-22T20:56:33.476-0500 [conn1] Enumerator: memo right after moving:
2014-01-22T20:56:33.476-0500 [conn1] [Node #0]: predicate, first indices: [0], pred: a == 17.0
indexToAssign: 0
2014-01-22T20:56:33.476-0500 [conn1] about to build solntree from tagged tree:
a == 17.0 || Selected Index #0 pos 0
2014-01-22T20:56:33.477-0500 [conn1] Planner: adding solution:
FETCH
---fetched = 1
---sortedByDiskLoc = 0
---getSort = [{ _fts: 1, _ftsx: 1 }, { a: 1 }, { a: 1, _fts: 1 }, { a: 1, _fts: 1, _ftsx: 1 }, ]
---Child:
------IXSCAN
---------keyPattern = { a: 1.0, _fts: "text", _ftsx: 1 }
---------direction = 1
---------bounds = field #0['a']: [17.0, 17.0], field #1['_fts']: [MinKey, MaxKey], field #2['_ftsx']: [MinKey, MaxKey]
---------fetched = 0
---------fetched = 0
---------sortedByDiskLoc = 0
---------getSort = [{ _fts: 1, _ftsx: 1 }, { a: 1 }, { a: 1, _fts: 1 }, { a: 1, _fts: 1, _ftsx: 1 }, ]
2014-01-22T20:56:33.477-0500 [conn1] Planner: outputted 1 indexed solutions.
2014-01-22T20:56:33.477-0500 [conn1] Planner: outputting a collscan:
2014-01-22T20:56:33.477-0500 [conn1] COLLSCAN
---ns = test.foo
--- filter = a == 17.0
---fetched = 1
---sortedByDiskLoc = 0
---getSort = []
2014-01-22T20:56:33.477-0500 [conn1] scoring plan 0:
FETCH
---fetched = 1
---sortedByDiskLoc = 0
---getSort = [{ _fts: 1, _ftsx: 1 }, { a: 1 }, { a: 1, _fts: 1 }, { a: 1, _fts: 1, _ftsx: 1 }, ]
---Child:
------IXSCAN
---------keyPattern = { a: 1.0, _fts: "text", _ftsx: 1 }
---------direction = 1
---------bounds = field #0['a']: [17.0, 17.0], field #1['_fts']: [MinKey, MaxKey], field #2['_ftsx']: [MinKey, MaxKey]
---------fetched = 0
---------fetched = 0
---------sortedByDiskLoc = 0
---------getSort = [{ _fts: 1, _ftsx: 1 }, { a: 1 }, { a: 1, _fts: 1 }, { a: 1, _fts: 1, _ftsx: 1 }, ]
2014-01-22T20:56:33.478-0500 [conn1] score (2) = baseScore (1) + productivity(0) + noFetchBonus(1)
2014-01-22T20:56:33.478-0500 [conn1] score = 2
2014-01-22T20:56:33.478-0500 [conn1] scoring plan 1:
COLLSCAN
---ns = test.foo
--- filter = a == 17.0
---fetched = 1
---sortedByDiskLoc = 0
---getSort = []
2014-01-22T20:56:33.478-0500 [conn1] score (2) = baseScore (1) + productivity(0) + noFetchBonus(1)
2014-01-22T20:56:33.478-0500 [conn1] score = 2
2014-01-22T20:56:33.478-0500 [conn1] Winning solution:
FETCH
---fetched = 1
---sortedByDiskLoc = 0
---getSort = [{ _fts: 1, _ftsx: 1 }, { a: 1 }, { a: 1, _fts: 1 }, { a: 1, _fts: 1, _ftsx: 1 }, ]
---Child:
------IXSCAN
---------keyPattern = { a: 1.0, _fts: "text", _ftsx: 1 }
---------direction = 1
---------bounds = field #0['a']: [17.0, 17.0], field #1['_fts']: [MinKey, MaxKey], field #2['_ftsx']: [MinKey, MaxKey]
---------fetched = 0
---------fetched = 0
---------sortedByDiskLoc = 0
---------getSort = [{ _fts: 1, _ftsx: 1 }, { a: 1 }, { a: 1, _fts: 1 }, { a: 1, _fts: 1, _ftsx: 1 }, ]
2014-01-22T20:56:33.478-0500 [conn1] not caching runner but returning 0 results