2016-04-01 5 views
0

デフォルト値が「エンジニアリング」の部門フィールドがあるユーザーモデルがあります。mongoid pluck - モデルにデフォルト値の正しい値が返されない

このフィールドは、私たちのウェブサイトが公開されてから2ヶ月後に導入され、そのmongo以来、移行はありませんでした。

私が使用してオブジェクトを取得しようとする場合は、正しい値が、私は値を摘み取るしようとした場合、それはゼロではなく、デフォルト値を返し、

User.find_by(:name => "John).department 

しかし返されます。

User.limit(2).pluck(:department) 

戻り

[nil,"Finance"] 

私は少しを調査し、私は同じ問題に直面しています考えて、このブログの記事http://ahmadsherif.com/blog/2013/01/29/mongoid-default-fields-can-give-you-hard-time/

に出くわしました。これのための回避策はありますか?私はそれがメモリを大量に消費することはなく、時間を節約するので、抜け出すことを選んだ。

+0

どのようにデフォルト値を設定していますか?実際にDBに保存されていますか? MongoDBには、従来のSQLデータベースのような「実際の」データベースレベルのデフォルトがないためです。 – max

答えて

1

ここでの振る舞いは、MongoDBがPostgresのような従来のリレーショナルデータベースとの違いを説明することで説明できます。

SQLの世界では、データベーススキーマを介してデフォルトを設定し、行を挿入するたびにDBがNULLフィールドを埋めます。

MongoDBはスキーマレスなので、ドキュメントのフィールドにはデフォルト値のnilがあります。これは変更できません。データベースレベルでデフォルトを定義できるスキーマがないためです。代わりに、デフォルトはアプリケーションレベルで実装されます。 Mongoidの場合、これは、新しいモデルインスタンスを初期化するときに、それらがnilであればデフォルト値を埋め込むことを意味します。 ActiveRecordの用語で

それは次のようになります。

class Thing < ActiveRecord::Base 
    after_initialize :set_default_foo, if: -> { self.foo.nil? } 

    private 
    def set_default_foo 
     self.foo = "bar" 
    end 
end 

をしかしあなたはMongoidがあなたのために既存の文書を更新していない既存の文書を持っており、既存のフィールドに新しいフィールドやデフォルトを追加した場合!

この2つのケースをどのように説明していますか?

User.find_by(:name => "John").department 
User.limit(2).pluck(:department) 

最初のケースでは、ドキュメントをストレージから取り出し、それを使用してモデルインスタンスを初期化します。モデルインスタンスが初期化されると、デフォルト値を設定するコールバックが実行されます。

.pluckが呼び出されると、Mongoidはモデルインスタンスを初期化せずに直接ストアから値を取得します。したがって、 "レガシー"のドキュメントの場合、それは無価値を返します。

これを解決するには、ドキュメントのデフォルト値をnilに設定する必要があります。

User.where(department: nil).update_all(department: 'engineering') 
関連する問題