2013-12-16 7 views
7

私はmongoengineと一緒に作業しており、簡単な移行を試みています。私はStringFieldからReferenceFieldに移行したいフィールドを別のObjectに持っています。私は手作業でマイグレーションを行い、まず古いStringFieldから来た文字列に基づいて新しいオブジェクトを構築し、それを明示的に設定することを計画しました。mongoengineの移行:InvalidId

フィールドタイプを変更すると、トップレベルのドキュメントにアクセスできなくなるという問題があります。新しいフィールドのプレースホルダとしてマイドキュメントのクラスコードに「ダミー」フィールドを作成する必要がありますか?これは私にとってクルージングのようですので、より良い方法があると思いますか?

これはエラーです。これは、DB(StringField)から出てくるフィールドが参照フィールドと一貫していないためです。

/usr/lib/python2.7/site-packages/mongoengine/queryset/base.pyc in __getitem__(self, key) 
    149     return queryset._get_as_pymongo(queryset._cursor.next()) 
    150    return queryset._document._from_son(queryset._cursor[key], 
--> 151             _auto_dereference=self._auto_dereference) 
    152   raise AttributeError 
    153 

/usr/lib/python2.7/site-packages/mongoengine/base/document.pyc in _from_son(cls, son, _auto_dereference) 
    568     try: 
    569      data[field_name] = (value if value is None 
--> 570           else field.to_python(value)) 
    571      if field_name != field.db_field: 
    572       del data[field.db_field] 

/usr/lib/python2.7/site-packages/mongoengine/fields.pyc in to_python(self, value) 
    935   not isinstance(value, (DBRef, Document, EmbeddedDocument))): 
    936    collection = self.document_type._get_collection_name() 
--> 937    value = DBRef(collection, self.document_type.id.to_python(value)) 
    938   return value 
    939 

/usr/lib/python2.7/site-packages/mongoengine/base/fields.pyc in to_python(self, value) 
    390  def to_python(self, value): 
    391   if not isinstance(value, ObjectId): 
--> 392    value = ObjectId(value) 
    393   return value 
    394 

/usr/lib/python2.7/site-packages/bson/objectid.pyc in __init__(self, oid) 
    88    self.__generate() 
    89   else: 
---> 90    self.__validate(oid) 
    91 
    92  @classmethod 

/usr/lib/python2.7/site-packages/bson/objectid.pyc in __validate(self, oid) 
    192      raise InvalidId("%s is not a valid ObjectId" % oid) 
    193    else: 
--> 194     raise InvalidId("%s is not a valid ObjectId" % oid) 
    195   else: 
    196    raise TypeError("id must be an instance of (%s, %s, ObjectId), " 

InvalidId: Was Dirty: a2111fe89383bb562738b81c2b63fe78e877ed32 is not a valid ObjectId 

答えて

0

私はいつも同じコレクション内の中間コレクションまたは中間フィールドを用いて手で物事を移行しましたが、this exampleは、あなたがしていないように見えます。スタックオーバーフローは外部リンクを嫌うので、私は下の例のような例を含めています。ところで、その "drop_collection"部分に注意してください!

import unittest 
from mongoengine import * 


class Test(unittest.TestCase): 

    def setUp(self): 
     conn = connect(db='mongoenginetest') 

    def create_old_data(self): 
     class Person(Document): 
      name = StringField() 
      age = FloatField() # Save as string 

      meta = {'allow_inheritance': True} 

     Person.drop_collection() 

     Person(name="Rozza", age=35.00).save() 

     rozza = Person._get_collection().find_one() 
     self.assertEqual(35.00, rozza['age']) 

    def test_migration(self): 

     self.create_old_data() 

     class Person(Document): 
      name = StringField() 
      age = StringField() 

      meta = {'allow_inheritance': True} 

     for p in Person.objects: 
      p.age = "%s" % p.age 
      p.save() 

     rozza = Person.objects.first() 
     self.assertEqual("35.0", rozza.age) 

if __name__ == '__main__': 
    unittest.main() 
0

私はあなたの移行スクリプトのために示唆している2つのオプション:あなたは、あなたがたObjectIdを読み、DBREFS

  • pymongoで移行をやって戻って保存できるようにする必要があります移行する必要がありますフィールド上DynamicFieldを使用して

    • 直接(pymongoのコレクションはPerson._get_collection()を介してアクセスできます)、項目をループすると、&を更新します。