ドット表記(オブジェクトの中へ)

based on v23 (2010-10-26更新) - オリジナル

MongoDBはJSON形式のオブジェクトを保存するようにデザインされています。  そして、このデータベースはオブジェクトの構造を理解し、クエリーの評価でオブジェクトの内側に入ることができます。

以下の形のオブジェクトを持っていると仮定します。

> db.persons.findOne()
{ name: "Joe", address: { city: "San Francisco", state: "CA" } ,
likes: [ 'scuba', 'math', 'literature' ] }

一番上のフィールドをクエリーするにはMongoのJSON形式のクエリ形式のオブジェクトで十分です。

> db.persons.find( { name : "Joe" } )

しかし、組み込みオブジェクトや配列を扱いたいときにはどうすればいいでしょうか。   これは、伝統的なRDBMSがするのとはちょっと違った考え方のクエリを使います。  組み込みオブジェクトを扱うには、"dot notation (ドット表記)"を使います。

> db.persons.find( { "address.state" : "CA" } )

配列の内側にアクセスするのは暗黙的に行われます。 配列のフィールド対するクエリの場合、データベースは自動的に配列の値を探しに行きます。

> db.persons.find( { likes : "math" } )

これらのスタイルを組み合わせることもできます。複雑な例です。

> db.blogposts.findOne()
{ title : "My First Post", author: "Jane",
comments : [{ by: "Abe", text: "First" },
{ by : "Ada", text : "Good post" } ]
}
> db.blogposts.find( { "comments.by" : "Ada" } )

また、それぞれのフィールドのキーにインデックスを作成することもできます。

db.persons.ensureIndex( { "address.state" : 1 } );
db.blogposts.ensureIndex( { "comments.by" : 1 } );

ドット表記 vs サブオブジェクト

nameと同様にauthor idがあると仮定してください。authorフィールドを保存するために、オブジェクトを使うことができます。

> db.blog.save({ title : "My First Post", author: {name : "Jane", id : 1}})

authorのnameがJaneのものすべてを探したいとき、ドット表記を使い、

> db.blog.findOne({"author.name" : "Jane"})

キーと値にマッチするオブジェクトだけを得るためには、オブジェクトを使い、

db.blog.findOne({"author" : {"name" : "Jane", "id" : 1}})

注意:

db.blog.findOne({"author" : {"name" : "Jane"}})

は、サブオブジェクトが完全にマッチしないといけないので、マッチしません({"name" : "Jane"} だけのオブジェクトにマッチします)。また、組み込みオブジェクトのキーの順序も完全に一致している必要があることに注意してください。

db.blog.findOne({"author" : {"id" : 1, "name" : "Jane"}})

これもまたマッチしません。

ポジションによる配列の要素へのアクセス

配列の要素は、配列のポジションによってアクセスすることもできます。

// i.e. comments[0].by == "Abe"
> db.blogposts.find( { "comments.0.by" : "Abe" } )

(上記の例は、MongoDBのシェルでのJavascriptの文法です。  同じ操作がMongoのドライバが存在する任意の言語ですることができます)

$elemMatch でのマッチング

$elemMatch クエリオペレータを使うと(mongod >= 1.3.1)、配列内の全体のドキュメントとマッチすることができます。例を使って説明します。コレクションの中に次のドキュメントがあると想定します。

// Document 1
{ "foo" : [
      {
        "shape" : "square",
        "color" : "purple",
        "thick" : false
      },
      {
        "shape" : "circle",
        "color" : "red",
        "thick" : true
      }
] }


// Document 2
{ "foo" : [
      {
        "shape" : "square",
        "color" : "red",
        "thick" : true
      },
      {
        "shape" : "circle",
        "color" : "purple",
        "thick" : false
      }
] }

ここで、 "purple かつ square" を探したいとすると、次のように書けます。

db.foo.find({"foo.shape": "square", "foo.color": "purple"})

このクエリでの問題は、一つ目のドキュメントに加え、二つ目のドキュメントにもマッチしてしまうということです。言い換えると、標準的なクエリーシンタックスは、 foo 配列内の一つのドキュメントだけに制限しません。上述したように、サブオブジェクトは完全に一致する必要があるので、

db.foo.find({foo: {"shape": "square", "color": "purple"} } )

もまたダメです。三つ目の属性"thick"があるからです。

foo配列の中で完全に一致するドキュメントを探すためには、 $elemMatch を使います。 "purple かつ square" を正しくクエリーするためには、 $elemMatchを次のように使います。

db.foo.find({foo: {"$elemMatch": {shape: "square", color: "purple"}}})

このクエリは "purple"と"square"を含め一つ目のドキュメントを返します。

参照


Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.

These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group.

blog comments powered by Disqus