MongoDB - データ型

提供: MochiuWiki : SUSE, EC, PCB

概要

BSON (Binary JSON) は、MongoDBがデータを保存および転送するために使用するバイナリ形式のドキュメントフォーマットである。
JSONを拡張した形式であり、JSONにはない追加のデータ型をサポートしている。

BSONは、以下に示す特徴を持つ。

  • 効率性
    バイナリ形式により、パースと生成が高速である。
  • トラバース性
    ドキュメント内の要素のサイズを含むため、スキャンが容易である。
  • 拡張性
    日付型、バイナリデータ型、ObjectId型など、JSONにはない型を追加している。


JSONとBSONの主な違いを以下に示す。

  • JSONはテキスト形式、BSONはバイナリ形式である。
  • JSONは制限されたデータ型のみをサポートするが、BSONは豊富なデータ型を提供する。
  • BSONは、MongoDBの内部表現として最適化されている。


MongoDBがBSONを採用している理由は、以下の通りである。

  • パフォーマンス
    バイナリ形式により、エンコード・デコードが高速である。
  • ストレージ効率
    データのサイズ情報を含むため、効率的なストレージ管理が可能である。
  • 型の豊富さ
    日付、バイナリデータ、ObjectIdなど、データベースに必要な型を直接サポートしている。


データ型の選択は、ストレージ効率とパフォーマンスに大きく影響する。
適切なデータ型を選択することで、以下に示すメリットが得られる。

  • ストレージサイズの最適化
    32ビット整数と64ビット整数の適切な使い分けによるディスク使用量の削減。
  • クエリパフォーマンスの向上
    インデックスサイズの最適化による検索速度の向上。
  • 精度の保証
    Decimal128型の使用による金融計算の正確性の確保。



BSONデータ型一覧

BSONでは、各データ型にType Number (整数識別子)Alias (文字列識別子) が割り当てられている。
これらの識別子は、クエリ時に $type 演算子で使用される。

BSONデータ型とType Number/Alias
Type Number Alias 型名 説明
1 "double" Double 倍精度浮動小数点数
2 "string" String UTF-8文字列
3 "object" Object 埋め込みドキュメント
4 "array" Array 配列
5 "binData" Binary Data バイナリデータ
6 "undefined" Undefined 廃止
7 "objectId" ObjectId 一意識別子
8 "bool" Boolean 論理型
9 "date" Date 日付時刻
10 "null" Null Null値
11 "regex" Regular Expression 正規表現
12 "dbPointer" DBPointer 廃止
13 "javascript" JavaScript JavaScriptコード
14 "symbol" Symbol 廃止
15 "javascriptWithScope" JavaScript with Scope スコープ付きJavaScript (非推奨)
16 "int" 32-bit Integer 32ビット整数
17 "timestamp" Timestamp 内部用タイムスタンプ
18 "long" 64-bit Integer 64ビット整数
19 "decimal" Decimal128 128ビット10進数
-1 "minKey" MinKey 最小値
127 "maxKey" MaxKey 最大値


$type 演算子を使用すると、ドキュメント内のフィールドの型を判定できる。
使用例を以下に示す。

 db.collection.find({ field: { $type: "string" } })
 db.collection.find({ field: { $type: 2 } })


特別なエイリアスとして number がある。
これは、intlongdoubledecimal の全ての数値型にマッチする。

 db.collection.find({ field: { $type: "number" } })



数値型

整数型

BSONは、32ビット整数と64ビット整数の2種類の整数型をサポートしている。

Int32 (32ビット整数)

32ビット符号付き整数型である。

  • Type Number
    16
  • Alias
    "int"
  • 範囲
    -2,147,483,648 〜 2,147,483,647 (-231 〜 231-1)
  • ストレージサイズ
    4バイト


MongoDB Shellでの使用例を以下に示す。

 db.collection.insertOne({
    count: NumberInt(100)
 })


Int64 (64ビット整数)

64ビット符号付き整数型である。

  • Type Number
    18
  • Alias
    "long"
  • 範囲
    -9,223,372,036,854,775,808 〜 9,223,372,036,854,775,807 (-263 〜 263-1)
  • ストレージサイズ
    8バイト


MongoDB Shellでの使用例を以下に示す。

 db.collection.insertOne({
    largeNumber: NumberLong("9223372036854775807")
 })


※注意
JavaScriptのNumber型は、精度の問題があるため、大きな整数値を扱う場合は NumberLong 関数を使用する必要がある。

浮動小数点型

Double (倍精度浮動小数点)

IEEE 754規格に準拠した64ビット倍精度浮動小数点数である。

  • Type Number
    1
  • Alias
    "double"
  • 範囲
    約±1.7E+308 (15〜17桁の精度)
  • ストレージサイズ
    8バイト


MongoDBでは、数値リテラルはデフォルトでDouble型として解釈される。

 db.collection.insertOne({
    price: 19.99
 })


Decimal128 (128ビット10進数)

IEEE 754-2008規格に準拠した128ビット10進浮動小数点数である。
金融計算など、高精度な10進演算が必要な場合に使用する。

  • Type Number
    19
  • Alias
    "decimal"
  • 精度
    34桁の10進数
  • 指数範囲
    -6143 〜 +6144
  • ストレージサイズ
    16バイト


MongoDB 3.4以降で利用可能である。
金額計算においては、浮動小数点数の丸め誤差を避けるため、Decimal128型の使用が強く推奨される。

使用例を以下に示す。

 db.collection.insertOne({
    totalAmount: NumberDecimal("12345.67")
 })


Decimal128とDoubleの比較例を以下に示す。

 db.test.insertOne({ doubleValue: 0.1 + 0.2 })
 db.test.insertOne({ decimalValue: NumberDecimal("0.1").add(NumberDecimal("0.2")) })
 
 db.test.find()


Double型では、0.30000000000000004 のような丸め誤差が発生する可能性があるが、Decimal128型では正確に 0.3 となる。

数値型の使い分け

各数値型の適切な使用場面を下表に示す。

数値型の適切な使用場面
データ型 適切な使用場面 不適切な使用場面
Int32 カウンタ、小さな整数値
(-21億 〜 +21億の範囲内)
大きな整数値
タイムスタンプ (ミリ秒)
Int64 タイムスタンプ (ミリ秒)
大きな整数値
IDやキー
金融計算
小数を含む値
Double 科学技術計算
統計値
座標値
金融計算
正確な10進演算が必要な場合
Decimal128 金融計算
通貨金額
正確な10進演算
整数値のみの場合
高速処理が必要な場合



文字列型

String型

UTF-8エンコーディングの文字列を格納する型である。

  • Type Number
    2
  • Alias
    "string"
  • エンコーディング
    UTF-8
  • 最大サイズ
    16MB (ドキュメント全体の最大サイズ制限内)


MongoDBの文字列は、全てUTF-8としてエンコードされるため、国際文字セット (日本語、中国語、アラビア語等) を直接サポートしている。

使用例を以下に示す。

 db.collection.insertOne({
    name: "山田太郎",
    description: "これはUTF-8でエンコードされた日本語の文字列です"
 })


文字列の検索例を以下に示す。

 # 通常の検索
 db.collection.find({ name: "山田太郎" })
 
 # 正規表現を使用した検索
 db.collection.find({ description: { $regex: "UTF-8" } })



バイナリ型

Binary Data (binData)

任意のバイナリデータを格納する型である。
画像、ファイル、暗号化されたデータ等の格納に使用される。

  • Type Number
    5
  • Alias
    "binData"
  • 最大サイズ
    16MB (ドキュメント全体の最大サイズ制限内)


Binary Data型には、用途を示すサブタイプが定義されている。
下表に、サブタイプの一覧を示す。

Binary Dataのサブタイプ
サブタイプ (16進数) 説明 使用状況
0x00 Generic binary subtype 汎用バイナリデータ
推奨
0x01 Function 関数データ
非推奨
0x02 Binary (Old) 旧形式のバイナリデータ
0x00の使用を推奨
0x03 UUID (Old) 旧形式のUUID
0x04の使用を推奨
0x04 UUID 新形式のUUID
推奨
0x05 MD5 MD5ハッシュ値
0x06 Encrypted BSON value 暗号化されたBSON値
MongoDB 4.2以降
0x80 User defined ユーザー定義サブタイプ
(0x80以降)


使用例を以下に示す。

 db.collection.insertOne({
    file: BinData(0, "aGVsbG8gd29ybGQ="),
    uuid: UUID("12345678-1234-5678-1234-567812345678")
 })


UUIDの生成と挿入の例を以下に示す。

 var uuid = UUID()
 db.collection.insertOne({
    userId: uuid,
    username: "user001"
 })



日付・時間型

Date型

日付と時刻を表現する型である。
Unixエポック (1970年1月1日 00:00:00 UTC) からのミリ秒数を、64ビット符号付き整数として格納する。

  • Type Number
    9
  • Alias
    "date"
  • 内部表現
    64ビット符号付き整数 (ミリ秒)
  • 範囲
    約2.9億年前 〜 約2.9億年後
  • 精度
    ミリ秒
  • タイムゾーン
    保存されない (UTC基準)


使用例を以下に示す。

 db.collection.insertOne({
    createdAt: new Date(),
    eventDate: ISODate("2024-12-25T09:00:00Z")
 })


特定の日付を指定する例を以下に示す。

 db.collection.insertOne({
    birthday: ISODate("1990-05-15T00:00:00Z")
 })


日付の範囲検索の例を以下に示す。

 db.collection.find({
    createdAt: {
       $gte: ISODate("2024-01-01T00:00:00Z"),
       $lt: ISODate("2025-01-01T00:00:00Z")
    }
 })


※注意
Dateオブジェクトは、タイムゾーン情報を保存しない。全ての日付はUTC基準で保存される。
アプリケーション側でタイムゾーン変換を行う必要がある。

Timestamp型

MongoDB内部で使用される特殊なタイムスタンプ型である。
主に、レプリケーション処理 や oplog で使用され、通常のアプリケーションでの使用は推奨されない。

  • Type Number
    17
  • Alias
    "timestamp"
  • 内部表現
    64ビット値
  • 用途
    MongoDB内部処理、レプリケーション、oplog


64ビット値の構成を以下に示す。

  • 上位32ビット
    time_t値 (Unixエポックからの秒数)
  • 下位32ビット
    増分カウンタ (ordinal)


この構成により、同じ秒内に発生した複数の操作を区別できる。

使用例を以下に示す (通常は自動的に設定される)。

 db.collection.insertOne({
    ts: Timestamp(1640995200, 1)
 })


※重要
通常のアプリケーションでは、Date型を使用すること。
Timestamp型は、MongoDB内部処理用である。


識別子型

ObjectId型

MongoDBのドキュメントを一意に識別するための12バイトの識別子である。
_id フィールドのデフォルト型として使用される。

  • Type Number
    7
  • Alias
    "objectId"
  • サイズ
    12バイト (96ビット)
  • 一意性
    グローバルに一意 (高確率)


ObjectIdの構成

12バイトのObjectIdは、以下に示すように構成される。

ObjectIdの12バイト構成
バイト位置 サイズ 内容 説明
0〜3 4バイト タイムスタンプ Unixエポックからの秒数
4〜8 5バイト ランダム値 プロセスごとに1回生成される。
<マシン識別子> + <プロセスID>
9〜11 3バイト カウンター ランダム値で初期化され、その後インクリメントされる


この構成により、以下に示す特性が保証される。

  • タイムスタンプ部分により、時系列での並び順が保たれる。
  • ランダム値により、異なるマシン・プロセス間での衝突が回避される。
  • カウンター部分により、同じ秒内に生成されたObjectIdの一意性が保たれる。


自動生成と手動設定

ObjectIdは、ドキュメント挿入時に自動的に生成される。

 db.collection.insertOne({
    name: "Alice"
 })


手動でObjectIdを指定することも可能である。

 db.collection.insertOne({
    _id: ObjectId("507f1f77bcf86cd799439011"),
    name: "Bob"
 })


新しいObjectIdを生成する例を以下に示す。

 var newId = ObjectId()
 db.collection.insertOne({
    _id: newId,
    name: "Charlie"
 })


ObjectIdからタイムスタンプを抽出

ObjectIdには、作成時刻の情報が含まれているため、タイムスタンプを抽出できる。

 var id = ObjectId("507f1f77bcf86cd799439011")
 var timestamp = id.getTimestamp()
 print(timestamp)


この機能を利用して、ドキュメントの作成日時でソートすることができる。

 db.collection.find().sort({ _id: 1 })



論理型

Boolean型

論理値 (真偽値) を表現する型である。

  • Type Number
    8
  • Alias
    "bool"
  • true または false
  • ストレージサイズ
    1バイト


使用例を以下に示す。

 db.collection.insertOne({
    isActive: true,
    isDeleted: false
 })


Boolean型を使用した検索例を以下に示す。

 db.collection.find({ isActive: true })
 
 # 論理演算子を使用した検索 (Not Equal)
 db.collection.find({ isActive: { $ne: true } })



Null型

Null型

値が存在しないこと または 未定義であることを表現する型である。

  • Type Number
    10
  • Alias
    "null"
  • null


使用例を以下に示す。

 db.collection.insertOne({
    name: "Alice",
    middleName: null
 })


Null値の検索例を以下に示す。

 db.collection.find({ middleName: null })


※重要な違い
nullと、フィールドが存在しない状態は異なる。

フィールドが存在しない場合を検索する例を以下に示す。

 db.collection.find({ middleName: { $exists: false } })


null または 存在しないフィールドを検索する例を以下に示す。

 db.collection.find({
    $or: [
       { middleName: null },
       { middleName: { $exists: false } }
    ]
 })



配列・オブジェクト型

配列型

複数の値を順序付きで格納する型である。

  • Type Number
    4
  • Alias
    "array"
  • 要素
    異なる型の値を含むことができる
  • ネスト
    配列の中に配列を含むことができる


使用例を以下に示す。

 db.collection.insertOne({
    tags: ["mongodb", "database", "nosql"],
    scores: [85, 90, 78],
    mixed: [1, "text", true, null]
 })


配列要素の検索例を以下に示す。

 db.collection.find({ tags: "mongodb" })

 db.collection.find({ tags: { $all: ["mongodb", "database"] } })

 db.collection.find({ scores: { $gt: 80 } })


ネストした配列の例を以下に示す。

 db.collection.insertOne({
    matrix: [
       [1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]
    ]
 })


オブジェクト型 (埋め込みドキュメント)

ドキュメント内に別のドキュメントを埋め込む型である。

  • Type Number
    3
  • Alias
    "object"
  • 構造
    キーと値のペア
  • ネスト
    オブジェクトの中にオブジェクトを含むことができる


使用例を以下に示す。

 db.collection.insertOne({
    name: "Alice",
    address: {
       street: "123 Main St",
       city: "Tokyo",
       zipCode: "100-0001"
    }
 })


埋め込みドキュメントのフィールドにアクセスする例を以下に示す。

 db.collection.find({ "address.city": "Tokyo" })


複数レベルのネストの例を以下に示す。

 db.collection.insertOne({
    user: {
       profile: {
          name: "Bob",
          age: 30,
          contact: {
             email: "bob@example.com",
             phone: "090-1234-5678"
          }
       }
    }
 })
 
 db.collection.find({ "user.profile.contact.email": "bob@example.com" })



特殊型

Regular Expression (正規表現型)

正規表現パターンを格納する型である。

  • Type Number
    11
  • Alias
    "regex"
  • 用途
    テキスト検索、パターンマッチング


使用例を以下に示す。

 db.collection.insertOne({
    pattern: /^[A-Z]/i
 })
 
 db.collection.find({ name: { $regex: /^john/i } })


JavaScript型

JavaScriptコードを格納する型である。

  • Type Number
    13
  • Alias
    "javascript"
  • 用途
    ストアドファンクション、サーバサイドスクリプト


使用例を以下に示す。

 db.collection.insertOne({
    code: Code("function() { return 42; }")
 })


JavaScript with Scope型 (非推奨)

スコープ (変数環境) 付きのJavaScriptコードを格納する型である。
MongoDB 4.4以降では非推奨となっている。

  • Type Number
    15
  • Alias
    "javascriptWithScope"
  • 状態
    非推奨 (MongoDB 4.4以降)


廃止された型

以下に示す型は、廃止されている。

Symbol型
  • Type Number
    14
  • Alias
    "symbol"
  • 状態
    廃止


DBPointer型
  • Type Number
    12
  • Alias
    "dbPointer"
  • 状態: 廃止


Undefined型
  • Type Number
    6
  • Alias
    "undefined"
  • 状態
    廃止



比較用特殊型

MinKey型

全ての値より小さい値を表現する特殊な型である。

  • Type Number
    -1
  • Alias
    "minKey"
  • 用途
    インデックス境界、シャーディング、比較演算


MinKeyは、BSON比較順序において最小の値として扱われる。
主に、シャーディングインデックスの範囲指定 で使用される。

使用例を以下に示す。

 db.collection.insertOne({
    key: MinKey()
 })


MaxKey型

全ての値より大きい値を表現する特殊な型である。

  • Type Number
    127
  • Alias
    "maxKey"
  • 用途
    インデックス境界、シャーディング、比較演算


MaxKeyは、BSON比較順序において最大の値として扱われる。
主に、シャーディングインデックスの範囲指定 で使用される。

使用例を以下に示す。

 db.collection.insertOne({
    key: MaxKey()
 })


使用場面

MinKeyとMaxKeyは、以下に示す場面で使用される。

  • シャーディング
    シャードキーの範囲を定義する際に、無限小・無限大を表現するために使用される。

  • インデックス境界
    インデックススキャンの範囲を指定する際に使用される。

  • 比較演算
    特殊な比較が必要な場合に使用される。



型の判定と変換

$type演算子

$type 演算子を使用すると、クエリ時にフィールドの型を判定できる。

  • Type Numberを使用した例
     db.collection.find({ age: { $type: 16 } })
    

  • Aliasを使用した例
     db.collection.find({ name: { $type: "string" } })
    

  • 複数の型を指定する例
     db.collection.find({ value: { $type: ["int", "long", "double"] } })
    

  • 特別なエイリアス number の使用例
    このクエリは、intlongdoubledecimal の全ての数値型にマッチする。
     db.collection.find({ value: { $type: "number" } })
    


型変換

$convert 演算子を使用すると、値の型を変換できる。

基本的な構文を以下に示す。

 {
    $convert: {
       input: <expression>,
       to: <type>,
       onError: <expression>,
       onNull: <expression>
    }
 }


文字列を整数に変換する例を以下に示す。

 db.collection.aggregate([
    {
       $project: {
          convertedValue: {
             $convert: {
                input: "$stringValue",
                to: "int",
                onError: 0,
                onNull: 0
             }
          }
       }
    }
 ])


下表に、主な変換パターンを示す。

主な型変換パターン
変換元 変換先
String Int32/Int64 "123" → 123
String Double "123.45" → 123.45
String Decimal128 "123.45" → NumberDecimal("123.45")
Int32/Int64 String 123 → "123"
Double String 123.45 → "123.45"
Date String ISODate("2024-01-01") → "2024-01-01T00:00:00.000Z"
String Date "2024-01-01" → ISODate("2024-01-01T00:00:00.000Z")
ObjectId String ObjectId(...) → "507f1f77bcf86cd799439011"


より簡潔な型変換演算子も利用可能である。

  • $toString
    文字列に変換
  • $toInt
    32ビット整数に変換
  • $toLong
    64ビット整数に変換
  • $toDouble
    Doubleに変換
  • $toDecimal
    Decimal128に変換
  • $toDate
    Dateに変換
  • $toObjectId
    ObjectIdに変換


使用例を以下に示す。

 db.collection.aggregate([
    {
       $project: {
          stringValue: { $toString: "$numericValue" },
          intValue: { $toInt: "$stringValue" }
       }
    }
 ])



RDBMSとの型対応

MongoDBのBSONデータ型と、MySQL / PostgreSQLのデータ型の対応を下表に示す。

MongoDBとRDBMSのデータ型対応
BSON型 Oracle Database 23ai SQL Server MySQL PostgreSQL 備考
Int32 NUMBER(10) INT INT INTEGER 32ビット整数
Int64 NUMBER(19) BIGINT BIGINT BIGINT 64ビット整数
Double BINARY_DOUBLE FLOAT DOUBLE DOUBLE PRECISION 倍精度浮動小数点
Decimal128 NUMBER(34, x)
(最大38桁)
DECIMAL(34, x)
(最大38桁)
DECIMAL(34, x)
(最大65桁)
NUMERIC(34, x)
(最大131072桁)
高精度10進数
String VARCHAR2
CLOB
VARCHAR
NVARCHAR
VARCHAR
TEXT
VARCHAR
TEXT
文字列
Boolean BOOLEAN (23ai以降)
NUMBER(1)
BIT BOOLEAN
TINYINT(1)
BOOLEAN 論理型
Date TIMESTAMP DATETIME2 DATETIME
TIMESTAMP
TIMESTAMP 日付時刻
Binary Data BLOB
RAW
VARBINARY
IMAGE
BLOB
VARBINARY
BYTEA バイナリデータ
ObjectId CHAR(24)
RAW(12)
CHAR(24)
BINARY(12)
CHAR(24)
BINARY(12)
CHAR(24)
BYTEA
一意識別子
Array JSON JSON
(SQL Server 2016以降)
JSON ARRAY
JSON
配列
Object JSON JSON
(SQL Server 2016以降)
JSON JSON
JSONB
オブジェクト
Null NULL NULL NULL NULL Null値


※注意
MongoDBのArrayとObjectは、ネイティブなデータ型である。

RDBMSでは、JSON型または専用のArray型を使用する必要がある。
MySQL 5.7以降、PostgreSQL 9.4以降でJSON型がサポートされている。


関連情報