Esempio n. 1
0
def _handle_unwind_stage(in_collection, unused_database, options):
    if not isinstance(options, dict):
        options = {'path': options}
    path = options['path']
    if not isinstance(path, six.string_types) or path[0] != '$':
        raise ValueError(
            '$unwind failed: exception: field path references must be prefixed '
            "with a '$' '%s'" % path)
    path = path[1:]
    should_preserve_null_and_empty = options.get('preserveNullAndEmptyArrays')
    include_array_index = options.get('includeArrayIndex')
    unwound_collection = []
    for doc in in_collection:
        try:
            array_value = helpers.get_value_by_dot(doc, path)
        except KeyError:
            if should_preserve_null_and_empty:
                unwound_collection.append(doc)
            continue
        if array_value is None:
            if should_preserve_null_and_empty:
                unwound_collection.append(doc)
            continue
        if array_value == []:
            if should_preserve_null_and_empty:
                new_doc = copy.deepcopy(doc)
                # We just ran a get_value_by_dot so we know the value exists.
                helpers.delete_value_by_dot(new_doc, path)
                unwound_collection.append(new_doc)
            continue
        if isinstance(array_value, list):
            iter_array = enumerate(array_value)
        else:
            iter_array = [(None, array_value)]
        for index, field_item in iter_array:
            new_doc = copy.deepcopy(doc)
            new_doc = helpers.set_value_by_dot(new_doc, path, field_item)
            if include_array_index:
                new_doc = helpers.set_value_by_dot(new_doc,
                                                   include_array_index, index)
            unwound_collection.append(new_doc)

    return unwound_collection
Esempio n. 2
0
 def test__set_value_by_dot(self):
     """Test set_value_by_dot"""
     for doc, key, expected in (
             ({}, 'a', {'a': 42}),
             ({'a': 1}, 'a', {'a': 42}),
             ({'a': {'b': 1}}, 'a', {'a': 42}),
             ({'a': {'b': 1}}, 'a.b', {'a': {'b': 42}}),
             ({'a': [{'b': 1}]}, 'a.0', {'a': [42]}),
             ({'a': [{'b': 1}]}, 'a.0.b', {'a': [{'b': 42}]})):
         ret = set_value_by_dot(doc, key, 42)
         assert ret is doc
         self.assertEqual(ret, expected)