首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MongoEngine DynamicDocument中的DictField问题

MongoEngine DynamicDocument中的DictField问题
EN

Stack Overflow用户
提问于 2016-04-27 07:58:48
回答 1查看 781关注 0票数 0

我的问题与Bountysource上的这篇文章相匹配:

https://www.bountysource.com/issues/32756263-attribute-error-when-building-nested-index-for-dictfield-in-dynamicdocument

我的工作场所使用PyMongo 2.6.3/MongoEngine 0.8.7已经有一段时间了,我们正在考虑升级到PyMongo 3.2.2/MongoEngine 0.10.6。我下载了这些版本并开始测试它们。我开始遇到一个基于使用DictFields的DynamicDocuments的类的问题。

代码语言:javascript
运行
复制
14:20:20  ERROR   nas.data.sync                            Traceback (most recent call last):
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/nas/data/sync.py", line 1484, in main
14:20:20  ERROR   nas.data.sync                                result = funct(external, syncRecord)
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/nas/data/sync.py", line 456, in syncAsset
14:20:20  ERROR   nas.data.sync                                success = scheduleUpdate(asset, v) and success
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/nas/data/sync.py", line 299, in scheduleUpdate
14:20:20  ERROR   nas.data.sync                                for wu in workunits:
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/queryset.py", line 80, in _iter_results
14:20:20  ERROR   nas.data.sync                                self._populate_cache()
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/queryset.py", line 92, in _populate_cache
14:20:20  ERROR   nas.data.sync                                self._result_cache.append(self.next())
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/base.py", line 1407, in next
14:20:20  ERROR   nas.data.sync                                raw_doc = self._cursor.next()
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/base.py", line 1481, in _cursor
14:20:20  ERROR   nas.data.sync                                self._cursor_obj = self._collection.find(self._query,
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/base.py", line 1515, in _query
14:20:20  ERROR   nas.data.sync                                self._mongo_query = self._query_obj.to_query(self._document)
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/visitor.py", line 90, in to_query
14:20:20  ERROR   nas.data.sync                                query = query.accept(QueryCompilerVisitor(document))
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/visitor.py", line 155, in accept
14:20:20  ERROR   nas.data.sync                                return visitor.visit_query(self)
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/visitor.py", line 78, in visit_query
14:20:20  ERROR   nas.data.sync                                return transform.query(self.document, **query.query)
14:20:20  ERROR   nas.data.sync                              File "E:/alpha_maya_pyside/auxiliary/__all/MongoEngine-0.10.6/mongoengine/queryset/transform.py", line 61, in query
14:20:20  ERROR   nas.data.sync                                raise InvalidQueryError(e)
14:20:20  ERROR   nas.data.sync                            InvalidQueryError: 'DictField' object has no attribute 'document_type'
14:20:20  ERROR   nas.data.sync                            sync failed

让类从Document继承而不是从DynamicDocument继承确实解决了这个问题。我一直在钻研MongoEngine的源代码,但没有什么能真正引起我的注意。我唯一的猜测是MongoEngine可能在将DynamicField转换为DictField时遇到了问题。

我添加了一个print语句MongoEngine-0.10.6/mongoengine/queryset/transform.py:

代码语言:javascript
运行
复制
try:
    fields = _doc_cls._lookup_field(parts)
    print fields
except Exception, e:
    raise InvalidQueryError(e)

在出现错误消息之前,我得到了以下输出:

代码语言:javascript
运行
复制
[<mongoengine.fields.DynamicField object at 0x00000000048B48D0>]
EN

回答 1

Stack Overflow用户

发布于 2016-04-28 09:25:18

我进入mongoengine/base/document.py并签出了__lookup_field函数。在该函数内部有一个相当长的if/else语句。以下是一段摘录。

代码语言:javascript
运行
复制
            if field is None:
                # Look up first field from the document
                if field_name == 'pk':
                    # Deal with "primary key" alias
                    field_name = cls._meta['id_field']
                if field_name in cls._fields:
                    field = cls._fields[field_name]
                elif cls._dynamic:
                    field = DynamicField(db_field=field_name)
                elif cls._meta.get("allow_inheritance", False) or cls._meta.get("abstract", False):
                    # 744: in case the field is defined in a subclass
                    for subcls in cls.__subclasses__():
                        try:
                            field = subcls._lookup_field([field_name])[0]
                        except LookUpError:
                            continue

                        if field is not None:
                            break
                    else:
                        raise LookUpError('Cannot resolve field "%s"' % field_name)
                else:
                    raise LookUpError('Cannot resolve field "%s"'
                                      % field_name)
            else:
                ReferenceField = _import_class('ReferenceField')
                GenericReferenceField = _import_class('GenericReferenceField')
                if isinstance(field, (ReferenceField, GenericReferenceField)):
                    raise LookUpError('Cannot perform join in mongoDB: %s' %
                                      '__'.join(parts))
                if hasattr(getattr(field, 'field', None), 'lookup_member'):
                    new_field = field.field.lookup_member(field_name)
                elif cls._dynamic and (isinstance(field, DynamicField) or
                                       getattr(getattr(field, 'document_type'), '_dynamic')):
                    new_field = DynamicField(db_field=field_name)

如果运行查询并使用StringField,那么变量field仍然是None。但是,如果使用DictField运行查询,则会将field设置为类似于<mongoengine.fields.DictField object at 0x0000000004506CF8>的值。我不知道field是如何设置为这个值的。无论如何,如果您正在查询的类恰好是一个DynamicDocument,那么您将被送到循环的这一部分。

代码语言:javascript
运行
复制
elif cls._dynamic and (isinstance(field, DynamicField) or
                                       getattr(getattr(field, 'document_type'), '_dynamic')):
                    new_field = DynamicField(db_field=field_name)

我是通过消除的过程得出这个结论的。基本上,我找出了我不想去的地方。正如您所看到的,由于DictField不是DynamicField,因此将向其查询document_type属性。DictField不具有导致InvalidQueryError的该属性。

看起来现在的解决方案是不要在DynamicDocuments中使用DictFields,或者看看是否可以在DynamicDocument中使用EmbeddedDocumentField、EmbeddedDocumentListField或ReferenceField。也许这就是开发人员的意图?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36877900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档