2013-12-16 14 views
7

Mongoengine ile çalışıyorum ve basit bir geçiş yapmaya çalışıyorum. StringField olmaktan başka bir Nesne'ye bir ReferenceField olmaktan geçmek istediğim bir alanım var. Yeni nesneyi eski StringField'tan gelen dizeye dayanarak ve sonra da açıkça belirleyerek, el ile geçişi yapmayı planladım.Mongoengine'deki Göçler: InvalidId

Sorun şu ki, alan türünü değiştirdikten sonra artık en üst düzey belgelere erişemiyorum. Dokümanın sınıf kodunda yeni alan için yer tutucu olarak "kukla" alan yaratılması gerekli mi? Bu bana daha iyi bir yol olduğunu düşündüğümden kludgy gibi görünüyor?

Hata, DB (StringField) 'dan çıkan alanın bir referans alanıyla tutarlı olmamasıdır.

/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 

cevap

0
Hep bir ara koleksiyon veya aynı koleksiyonunda bir ara alanını kullanarak elle şeyler göç ettik

ama this example sen gerekmez gibi görünmesini sağlar. Yığın taşması dış bağlantılardan nefret ediyor, bu yüzden aşağıdaki örnek verbatim'i ekliyorum. BTW bu "drop_collection" bölümüne dikkat et!

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

Ben senin göç komut dosyası için öneririm 2 seçenek: Eğer ObjectIds okuyup DBRefs

  • pymongo içinde taşınması işlemini geri saklamak için izin vermelidir taşımanız gerekiyor sahada DynamicField kullanarak

    • doğrudan (pymongo koleksiyonuna Person.get_collection() aracılığıyla erişilebilir) ve öğelerin üzerinde döngü yaparak &
  • İlgili konular