Docs Menu

フィールド型

このガイドでは、 MongoDBドキュメントのスキーマを定義するために使用できる Mongoid でサポートされているフィールド型について説明します。

MongoDB は、ドキュメントフィールドに保存されているデータ型を表すために BSON types を使用します。MongoidアプリケーションでBSONデータを使用するには、Mongoid は実行時にBSON型をRuby型に変換する必要があります。 例、データベースからドキュメントを取得する場合、Mongoid はBSON double 型をRuby Float 型を使用するように変換します。 ドキュメントを再度保存すると、Mongoid はフィールドをBSON double に変換します。

Mongoid でドキュメントをモデル化する方法の詳細については、「 モデルにドキュメント モジュールを含める 」ガイドを参照してください。

注意

モデルクラスでフィールド定義を変更しても、データベースに保存されているデータは変更されません。 データベースのフィールドのデータ型を変更するには、データを再度再保存する必要があります。

モデル クラスでフィールド名とタイプを定義するには、field マイクロと type マイクロを使用します。 次の例では、 Personクラスのフィールドを定義します。

class Person
include Mongoid::Document
field :name, type: String
field :date_of_birth, type: Date
field :weight, type: Float
end

次のリストは、Mongoid で使用できるフィールド型を示しています。

  • Array

  • Bson::Binary

  • BigDecimal

  • Mongoid::Boolean or Boolean

  • Date

  • DateTime

  • Float

  • Hash

  • Integer

  • Object

  • Bson::ObjectId

  • Range

  • Regexp

  • Set

  • String

  • Mongoid::StringifiedSymbol

  • Time

  • ActiveSupport::TimeWithZone

注意

Mongoid はフィールドタイプとして BSON::Int64 または BSON::Int32 をサポートしていません。 Mongoid はこれらの値をデータベースに正しく保存しますが、ドキュメントを取得すると、フィールドは Integer 型として返されます。

同様に、BSON::Decimal128 型のフィールドをクエリすると、Mongoid はそれらを BigDecimal 型として返します。

フィールドの型を指定しない場合、Mongoid はそれをデフォルトのObject 型として解釈します。 型指定されていないフィールドには、 BSONに直接シリアル化可能な任意の型の値を保存できます。 フィールドにさまざまなタイプのデータが含まれる可能性がある場合、またはフィールドの値のタイプが不明な場合は、フィールドを型なしで残すことができます。

次の例では、型指定されていないフィールドを持つ Productクラスを定義します。

class Product
include Mongoid::Document
field :name, type: String
field :properties
end

propertiesフィールドのタイプは Object ですが、そのフィールドに保存されているデータのタイプによって異なります。 次の例では、 2 つの異なる方法で propertiesフィールドにデータを保存します。

product = Product.new(properties: "color=white,size=large")
# properties field saved as String: "color=white,size=large"
product = Product.new(properties: {color: "white", size: "large"})
# properties field saved as Object: {:color=>"white", :size=>"large"}

Mongoid はデータベースから読み取るときに型のないフィールドで型の変換を実行しないため、特別な処理を必要とする値は、型なしフィールドの値として では正しく検索されない可能性があります。 次のBSONデータ型は、型なしフィールドに保存しないでください。

  • Date: 型なしフィールドで Time として返します

  • DateTime: 型なしフィールドで Time として返します

  • Range: 型なしフィールドで Hash として返します

Hash 型を使用して、フィールドに Hash データを保存できます。 フィールドをHash として指定する場合は、値がデータベースに正しく保存されるようにMongoDB の命名制限 に従っていることを確認してください。

次の例では、 Personクラスを作成し、urlフィールドをHash として指定します。

class Person
include Mongoid::Document
field :first_name
field :url, type: Hash
end
person = Person.new(url: {'home_page' => 'http://www.homepage.com'})

Timeフィールド値を使用して、 BSON Time インスタンスとして値を保存できます。 Time フィールドは、アプリケーションに構成されたタイムゾーンに保存されます。 タイム ゾーンの設定の詳細については、 アプリケーション構成ガイドの「 タイム ゾーン構成 」セクションを参照してください。

次の例では、 Voterクラスを作成し、registered_atフィールドの値が Time 型であることを指定します。

class Voter
include Mongoid::Document
field :registered_at, type: Time
end
Voter.new(registered_at: Date.today)

注意

Time として指定されたフィールドに Date または DateTime の値を保存すると、割り当て時に値が Time に変換されます。 string を Timeフィールドに保存すると、Mongoid は Time.parse メソッドを使用して string を解析します。 Mongoid がクエリを変換する方法の詳細については、 クエリの指定ガイドの「 フィールド型クエリ変換 」セクションを参照してください。

Date として指定されたフィールドには次の値の型を保存できます。

  • Date: 指定された値を保存します。

  • Time: 値の日付部分を値の タイムゾーンに保存します。

  • DateTime: 値の日付部分を値の タイムゾーンに保存します。

  • ActiveSupport::TimeWithZone: 値の日付部分を値の タイムゾーンに保存します。

  • String: string で指定された日付を保存します。

  • Integer: UTC タイムスタンプであるかのように値を受け取り、アプリケーションの設定された タイムゾーンに変換します。 次に、Mongoid はそのタイムスタンプから取得された日付を保存します。

  • Float: UTC タイムスタンプであるかのように値を受け取り、アプリケーションの設定された タイムゾーンに変換します。 次に、Mongoid はそのタイムスタンプから取得された日付を保存します。

Time または DateTime を変換すると時間部分が破棄されるため、フィールドに割り当てる前に、StringTimeDateTime オブジェクトを Date に明示的に変換することをお勧めします。

注意

データベースにDateフィールドの string 値が含まれている場合、ドライバーは Time.parse メソッドを使用して値を解析し、時間部分を破棄します。 Time.parse では、タイムゾーンのない値はローカル時間であると見なされます。 Mongoid がクエリを変換する方法の詳細については、 クエリの指定ガイドの「 フィールド型クエリ変換 」セクションを参照してください。

これらのフィールドに対して DateTime または クエリとして定義されたフィールドに値を割り当てると、Mongoid は値を UTC Time 値に変換してからMongoDBサーバーに送信します。 Mongoid は、DateTimeオブジェクトに埋め込まれたタイムゾーンを含む値を保存します。 値を取得すると、Mongoid は UTC 時間をアプリケーションに構成されたタイムゾーンに変換します。

次の例では、 Ticketクラスを作成し、purchased_atフィールドをDateTimeフィールドとして指定します。

class Ticket
include Mongoid::Document
field :purchased_at, type: DateTime
end

整数値または浮動小数数値を DateTimeフィールドに保存すると、その値は UTC の Unix タイムスタンプとして扱われます。 次の例では、 purchased_atフィールドに整数値を保存しています。

ticket.purchased_at = 1544803974
ticket.purchased_at
# Outputs: Fri, 14 Dec 2018 16:12:54 +0000

string の値を DateTimeフィールドに保存すると、Mongoid は指定されたタイムゾーンのチケットを保存します。 タイムゾーンが指定されていない場合、Mongoid はアプリケーションのデフォルトとして構成されたタイムゾーン を使用して 値を保存します。

ticket.purchased_at = 'Mar 4, 2018 10:00:00 +01:00'
ticket.purchased_at
# Outputs: Sun, 04 Mar 2018 09:00:00 +0000

タイム ゾーンの設定の詳細については、 アプリケーション構成ガイドの「 タイム ゾーン構成 」セクションを参照してください。

注意

Mongoid は Time.parse メソッドを使用して string 値を DateTime に解析します。このメソッドでは、タイムゾーンのない値はローカル時間であると見なされます。

クラスを作成する ときに、Mongoid::Timestamps モジュールを含めることで、クラスにタイムスタンプ フィールドを含めることができます。 Mongoid::Timestamps を含めると、Mongoid はクラスに次のフィールドを作成します。

  • created_at:ドキュメントが作成された時刻を保存します。

  • updated_at:ドキュメントが最後にアップデートされた時刻を保存します。

次の例では、タイムスタンプ フィールドを持つ Postクラスを作成しています。

class Post
include Mongoid::Document
include Mongoid::Timestamps
end

また、Created または Updated モジュールのみを含めることで、created_at フィールドまたは updated_at フィールドのみを含めることもできます。 次の例では、 created_atフィールドのみを含む Postクラスと、updated_atフィールドのみを含む Postクラスを作成します。

class Post
include Mongoid::Document
include Mongoid::Timestamps::Created
end
class Post
include Mongoid::Document
include Mongoid::Timestamps::Updated
end

モジュールを含めるときに ::Short オプションを設定することで、タイムスタンプフィールド名を c_atu_at に短縮できます。

class Post
include Mongoid::Document
include Mongoid::Timestamps::Short # For c_at and u_at.
end
class Post
include Mongoid::Document
include Mongoid::Timestamps::Created::Short # For c_at only.
end
class Post
include Mongoid::Document
include Mongoid::Timestamps::Updated::Short # For u_at only.
end

メソッド呼び出しで timeless メソッドを呼び出すと、特定の操作のタイムスタンプフィールドの作成を無効にできます。 次の例ではsave操作のタイムスタンプを無効にします。

post.timeless.save

Regexp 型を使用して、フィールドに正規表現を保存できます。

MongoDB はPerl互換正規表現(PCRE) を実装しますが、Mongoid は Ruby の Onigmo ライブラリを使用します。PCRE と Onigmo は通常同じ機能を提供しますが、構文の違いがいくつかあります。 例、Onigmo では string の先頭と末尾を一致させるために \A\z が使用され、PCRE では ^$ が使用されます。

フィールドをRegexp として宣言すると、Mongoid は結果をデータベースに保存 するときにRuby正規表現をBSON正規表現に変換します。 データベースはフィールドをBson::Regexp::Rawインスタンスとして返します。 BSON::Regexp::Raw インスタンスで compile メソッドを使用して、データをRuby正規式に変換できます。

次の例では、 Tokenクラスを作成し、patternフィールドをRegexp として指定します。

class Token
include Mongoid::Document
field :pattern, type: Regexp
end
token = Token.create!(pattern: /hello.world/m)
token.pattern
# Outputs: /hello.world/m
# Reload the token from the database
token.reload
token.pattern
# Outputs: #<BSON::Regexp::Raw:0x0000555f505e4a20 @pattern="hello.world", @options="ms">

重要

BSON正規式をRuby正規式に変換すると、元とは異なる正規式が生成される可能性があります。 この違いは、Onigmo と PCRE の構文規則が異なるためです。 Mongoid の正規表現の詳細については、 クエリの指定ガイドの「 正規表現 」セクションを参照してください。

より精度の高い数値を保存するには、 BigDecimal 型を使用します。 Mongoid は、Mongoid.map_big_decimal_to_decimal128 構成プロパティに設定した値に応じて、BigDecimal 値を 2 つの異なる方法で保存します。

  • true に設定すると、Mongoid は BigDecimal 値をBSON Decimal128 値として保存します。

  • false(デフォルト)に設定されている場合、Mongoid は BigDecimal 値を string として保存します。

Mongoid.map_big_decimal_to_decimal128 オプションを true に設定する場合は、次の制限を考慮してください。

  • Decimal128 は、範囲と精度が制限されています。 Decimal128 の最大値は約 10^6145、最小値は約 -10^6145 で、精度は最大 34 ビットです。 これらの制限外の値を保存する場合は、代わりに string として保存することをお勧めします。

  • Decimal128 は符号付き NaN 値を受け入れますが、BigDecimal は一致しません。 符号付き NaN Decimal128 値を BigDecimal としてデータベースから取得すると、符号なしの値が返されます。

  • Decimal128 は後続のゼロを保持しますが、BigDecimal は後続のゼロを保持しません。 このため、データベースから Decimal128 の値を BigDecimal として検索すると、精度が失われる可能性があります。

注意

Mongoid.map_big_decimal_to_decimal128 オプションを false に設定し、BigDecimal を型なしフィールドに保存している場合、フィールドをBigDecimal としてクエリすることはできません。 値は string として保存されているため、型なしフィールドで BigDecimal 値をクエリしても、 データベース内の値は見つかりません。 値を見つけるには、まずクエリ値を string に変換する必要があります。

この問題を回避するには、フィールドを型なしではなく BigDecimal 型として指定します。

Rubyアプリケーションにシンボルとして公開する値を保存するには、StringifiedSymbolフィールド型を使用します。 StringifiedSymbol を使用すると、他のドライバーとの相互運用性を確保しながら、 シンボルを使用できます。 このタイプは、データベース上のすべてのデータを string として保存し、アプリケーションによって読み取られるときに string をシンボルに変換します。 整数や配列など、記号に直接変換できない値は、string に変換され、その後記号に変換されます。

次の例では、 statusフィールドをStringifiedSymbol として定義し、このフィールドの保存方法と返却方法を示しています。

class Post
include Mongoid::Document
field :status, type: StringifiedSymbol
end
# Save status as a symbol
post = Post.new(status: :hello)
# status is stored as "hello" on the database, but returned as a Symbol
post.status
# Outputs: :hello
# Save status as a string
post = Post.new(status: "hello")
# status is stored as "hello" in the database, but returned as a Symbol
post.status
# Outputs: :hello

Mongoid 内の特定のフィールドタイプを指定するには、クラス名を使用する代わりに文字列または記号を使用します。 次の例では、クラス名、string、記号を使用して order_numフィールドを指定します。

class Order
include Mongoid::Document
# Class Name
field :order_num, type: Integer
# Symbol
field :order_num, type: :integer
# String
field :order_num, type: "integer"
end

次の表に、string または記号として指定できるフィールドタイプを示します。

クラス名
シンボル
文字列

Array

:array

"Array"

BigDecimal

:big_decimal

"BigDecimal"

BSON::Binary

:binary

"BSON::Binary"

Mongoid::Boolean

:boolean

"Mongoid::Boolean"

Date

:date

"Date"

DateTime

:date_time

"DateTime"

Float

:float

"Float"

Hash

:hash

"Hash"

Integer

:integer

"Integer"

BSON::ObjectId

:object_id

"BSON::ObjectId"

Range

:range

"Range"

Regexp

:regexp

"Regexp"

Set

:set

"Set"

String

:string

"String"

StringifiedSymbol

:stringified_symbol

"StringifiedSymbol"

Symbol

:symbol

"Symbol"

Time

:time

"Time"

カスタムフィールドタイプを作成し、Mongoid がそれらを直列化および逆直列化する方法を定義できます。 カスタムフィールドタイプを作成するには、次のメソッドを実装するクラスを定義します。

  • mongoize: カスタム型のインスタンスを受け取り、 MongoDB が保存できるオブジェクトに変換します。

  • demongoize: MongoDBからオブジェクトを取得し、それをカスタム型のインスタンスに変換します。

  • evolve: カスタム型のインスタンスを取得し、それをMongoDB がデータベース をクエリするために使用できる基準に変換します。

次の例では、 Point というカスタムフィールド型を作成し、上記のメソッドを実装しています。

class Point
attr_reader :x, :y
def initialize(x, y)
@x, @y = x, y
end
# Converts an object of this instance into an array
def mongoize
[ x, y ]
end
class << self
# Takes any possible object and converts it to how it is
# stored in the database.
def mongoize(object)
case object
when Point then object.mongoize
when Hash then Point.new(object[:x], object[:y]).mongoize
else object
end
end
# Gets the object as it's stored in the database and instantiates
# this custom class from it.
def demongoize(object)
if object.is_a?(Array) && object.length == 2
Point.new(object[0], object[1])
end
end
# Converts the object supplied to a criteria and converts it
# into a queryable form.
def evolve(object)
case object
when Point then object.mongoize
else object
end
end
end
end

前の例では、mongoize インスタンスメソッドはカスタム型オブジェクトのインスタンスを受け入れ、それをArray に変換してデータベースに保存します。mongoizeクラスメソッドは、すべての型のオブジェクトを受け入れ、データベースに保存できる同様の型に変換します。Mongoid は、getter メソッドと setter メソッドを呼び出すときに mongoizeクラスメソッドを使用します。

demongoize メソッドは、保存された Array 値をカスタム Point 型に変換します。 Mongoid は、 getter を呼び出すときにこのメソッドを使用します。

evolve メソッドは、カスタム Point 型をクエリ可能な Array 型に変換し、他のすべての型を object に変換します。 Mongoid は、データベース をクエリするメソッドを呼び出すときにこのメソッドを使用します。

アプリケーションに割り当てられた値とは異なる値をデータベースに保存するカスタムフィールドタイプを作成できます。 これは、データベースにより圧縮された値を保存しながら、アプリケーションに記述的な値を設定するのに便利です。

次の例では、アプリケーション内の色の名前を使用する ColorMapping 型を作成しますが、データベースには整数として色を保存します。

class ColorMapping
MAPPING = {
'black' => 0,
'white' => 1,
}.freeze
INVERSE_MAPPING = MAPPING.invert.freeze
class << self
def mongoize(object)
MAPPING[object]
end
def demongoize(object)
INVERSE_MAPPING[object]
end
def evolve(object)
MAPPING.fetch(object, object)
end
end
end
class Profile
include Mongoid::Document
field :color, type: ColorMapping
end
profile = Profile.new(color: 'white')
profile.color
# Outputs: "white"
# Sets "color" field to 0 in MongoDB
profile.save!

モデルに Mongoid::Attributes::Dynamic モジュールを含めることで、Mongoid にフィールドを動的に作成するように指示できます。 これにより、Mongoid は任意のハッシュに基づいて、またはデータベースにすでに保存されているドキュメントに基づいてフィールドを作成できます 。

次の例では、動的フィールドを持つ Personクラスを作成します。

class Person
include Mongoid::Document
include Mongoid::Attributes::Dynamic
end

Tip

同じクラス内で固定フィールドと動的フィールドの両方を指定できます。 この場合、Mongoid は、フィールドタイプに応じてフィールド定義を持つプロパティのすべての属性と、他のすべての属性を動的として扱います。

アプリケーションで 動的フィールド を使用する場合は、最初に次のいずれかの方法で値を設定する必要があります。

  • 属性ハッシュを コンストラクターに渡します。

  • attributes= メソッドを使用して値を割り当てます。

  • []= メソッドを使用して値を割り当てます。

  • write_attribute メソッドを使用して値を割り当てます。

  • データベースにすでに存在する値を操作します。

上記のオプションのいずれかを使用して最初に値を設定しない場合、属性を呼び出すと NoMethodError が返されます。

Mongoid とMongoDB Query APIではどちらも、ネストされたドキュメント内のフィールド名を区切るために . 文字と、クエリ演算子 を示すために string の先頭に $ 文字が予約されています。 このため、フィールド名にこれらの文字を使用することは避けてください。

アプリケーションでこれらの文字を使用する必要がある場合は、send メソッドを呼び出してフィールドにアクセスできます。 次の例では、予約文字を含むフィールドを持つ Userクラスを作成しています。 次に、send メソッドを使用してフィールドにアクセスします。

class User
include Mongoid::Document
field :"first.last", type: String
field :"$_amount", type: Integer
end
user = User.first
user.send(:"first.last")
# Outputs: Mike.Trout
user.send(:"$_amount")
# Outputs: 42650000

また、read_attribute メソッドを呼び出してこれらのフィールドにアクセスすることもできます。

重要

これらの予約文字を含むフィールドの更新と置換には特別な演算子が必要になるため、これらのフィールドで getter と setter を呼び出すと InvalidDotDollarAssignment 例外が発生します。