diff options
author | Benety Goh <benety@mongodb.com> | 2014-02-06 11:52:13 -0500 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2014-02-07 13:16:44 -0500 |
commit | e01492875083bf30bba35b38a8a0301e66c422df (patch) | |
tree | 4f2c1e31f96ce38c9f07fdd148db6aaa8e9abe16 /src/mongo | |
parent | 795353195c696a95a6f18a4deb38dfb5ad588ab9 (diff) | |
download | mongo-e01492875083bf30bba35b38a8a0301e66c422df.tar.gz |
SERVER-12129 meta projection operator should overwrite fields
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/exec/projection_exec.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/exec/projection_exec.h | 4 | ||||
-rw-r--r-- | src/mongo/db/exec/projection_exec_test.cpp | 30 |
3 files changed, 40 insertions, 2 deletions
diff --git a/src/mongo/db/exec/projection_exec.cpp b/src/mongo/db/exec/projection_exec.cpp index 05a33a24002..15a224cbe72 100644 --- a/src/mongo/db/exec/projection_exec.cpp +++ b/src/mongo/db/exec/projection_exec.cpp @@ -479,6 +479,14 @@ namespace mongo { const MatchDetails* details, const ArrayOpType arrayOpType) const { + + // Skip if the field name matches a computed $meta field. + // $meta projection fields can exist at the top level of + // the result document and the field names cannot be dotted. + if (_meta.find(elt.fieldName()) != _meta.end()) { + return Status::OK(); + } + FieldMap::const_iterator field = _fields.find(elt.fieldName()); if (field == _fields.end()) { if (_include) { diff --git a/src/mongo/db/exec/projection_exec.h b/src/mongo/db/exec/projection_exec.h index eefeb5e8c9a..796e8c62283 100644 --- a/src/mongo/db/exec/projection_exec.h +++ b/src/mongo/db/exec/projection_exec.h @@ -178,10 +178,10 @@ namespace mongo { ArrayOpType _arrayOpType; - // Is there an elemMatch or positional operator? + // Is there an slice, elemMatch or meta operator? bool _hasNonSimple; - // Is there a projection over a dotted field? + // Is there a projection over a dotted field or a $ positional operator? bool _hasDottedField; // The full query expression. Used when we need MatchDetails. diff --git a/src/mongo/db/exec/projection_exec_test.cpp b/src/mongo/db/exec/projection_exec_test.cpp index 6267f32fabe..59af37dd6d4 100644 --- a/src/mongo/db/exec/projection_exec_test.cpp +++ b/src/mongo/db/exec/projection_exec_test.cpp @@ -34,6 +34,7 @@ #include <memory> #include "mongo/db/json.h" +#include "mongo/db/exec/working_set_computed_data.h" #include "mongo/db/matcher/expression_parser.h" #include "mongo/unittest/unittest.h" @@ -64,12 +65,14 @@ namespace { * specStr - projection specification * queryStr - query * objStr - object to run projection on + * data - computed data. Owned by working set member created in this function if not null. * expectedStatusOK - expected status of transformation * expectedObjStr - expected object after successful projection. * Ignored if expectedStatusOK is false. */ void testTransform(const char* specStr, const char* queryStr, const char* objStr, + WorkingSetComputedData* data, bool expectedStatusOK, const char* expectedObjStr) { // Create projection exec object. BSONObj spec = fromjson(specStr); @@ -81,6 +84,9 @@ namespace { WorkingSetMember wsm; wsm.state = WorkingSetMember::OWNED_OBJ; wsm.obj = fromjson(objStr); + if (data) { + wsm.addComputed(data); + } // Transform object Status status = exec.transform(&wsm); @@ -125,6 +131,14 @@ namespace { } } + /** + * testTransform without computed data argument. + */ + void testTransform(const char* specStr, const char* queryStr, const char* objStr, + bool expectedStatusOK, const char* expectedObjStr) { + testTransform(specStr, queryStr, objStr, NULL, expectedStatusOK, expectedObjStr); + } + // // position $ // @@ -186,4 +200,20 @@ namespace { testTransform("{a: {$slice: [10, 10]}}", "{}", "{a: [4, 6, 8]}", true, "{a: []}"); } + // + // $meta + // $meta projections add computed values to the projected object. + // + + TEST(ProjectionExecTest, TransformMetaTextScore) { + // Query {} is ignored. + testTransform("{b: {$meta: 'textScore'}}", "{}", "{a: 'hello'}", + new mongo::TextScoreComputedData(100), + true, "{a: 'hello', b: 100}"); + // Projected meta field should overwrite existing field. + testTransform("{b: {$meta: 'textScore'}}", "{}", "{a: 'hello', b: -1}", + new mongo::TextScoreComputedData(100), + true, "{a: 'hello', b: 100}"); + } + } // namespace |