2015/06/02更新

[Mongo] findメソッドのいろいろな使い方(MySQLと比較)

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
以前にフロントエンドエンジニアにオススメなデータベース、MongoDBに入門フロントエンドエンジニアにもできるMongoDBを使ったログ分析のブログを書いたのち、MongoDBを引き続き使っていますが、findの使い方を調べることが多く、今回はそれらをブログに残しておきたいと思います。

画像

https://flic.kr/p/55XJ83




目次




Mongoの検索メソッドは多機能

MongoのfindfindOnecountdistinctは検索を行うことができるメソッドたちです。使うときそれぞれのユースケースに合わせた使い分けをしていく必要があり、それぞれのメソッドの機能をある程度知っている必要があります。今回はSQLのselect文をMongoで実現するにはという切り口で、Mongoの検索機能を学んでみたいと思います。



今回利用するデータ

今回は以下のようなUserデータを使って説明してみたいと思います。
db.users.insert({user_id: "abc001", age: 45, status: "A"})
db.users.insert({user_id: "bcd001", age: 50, status: "A"})
db.users.insert({user_id: "cde001", age: 20, status: "A"})
db.users.insert({                   age: 10, status: "A"})
db.users.insert({user_id: "def001", age: 30, status: "B"})



検索メソッドのいろいろな使い方

それではいろいろな使い方をみてみたいと思います。


全件検索する

// SQL
SELECT * FROM users
// Mongo
db.users.find()
// 実行結果
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }
{ "_id" : ObjectId("556d56b5aa73f980c884bf53"), "user_id" : "def001", "age" : 30, "status" : "B" }
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "age" : 10, "status" : "A" }


検索フィールドを指定する

// SQL
SELECT id, user_id, status FROM users
// Mongo
db.users.find(
    {},
    {user_id: 1, status: 1}
)
// 実行結果(ageは含まれない)
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "status" : "A" }
{ "_id" : ObjectId("556d56b5aa73f980c884bf53"), "user_id" : "def001", "status" : "B" }
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "status" : "A" }


検索フィールドを指定する(_idを除く)

// SQL
SELECT user_id, status FROM users
// Mongo
db.users.find(
    {},
    {user_id: 1, status: 1, _id: 0}
)
// 実行結果(_idが含まれない)
{ "user_id" : "abc001", "status" : "A" }
{ "user_id" : "bcd001", "status" : "A" }
{ "user_id" : "cde001", "status" : "A" }
{ "user_id" : "def001", "status" : "B" }
{ "status" : "A" }


検索条件を指定する(等価比較)

// SQL
SELECT * FROM users WHERE status = "A"
// Mongo
db.users.find(
    {status: "A"}
)
// 実行結果(status=Aのデータのみ)
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "age" : 10, "status" : "A" }


検索条件を指定する(非等価比較)

// SQL
SELECT * FROM users WHERE status != "A"
// Mongo
db.users.find(
    {status: { $ne: "A" }}
)
// 実行結果(status!=Aのデータのみ)
{ "_id" : ObjectId("556d56b5aa73f980c884bf53"), "user_id" : "def001", "age" : 30, "status" : "B" }


検索条件を複数指定する

// SQL
SELECT * FROM users WHERE status = "A" AND age = 50
// Mongo
db.users.find(
    {status: "A", age: 50}
)
// 実行結果(status=A AND age=50 のデータのみ)
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }


OR条件を指定する

// SQL
SELECT * FROM users WHERE status = "A" OR age = 50
// Mongo
db.users.find(
    {$or: [{status: "A"} , {age: 50}]}
)
// 実行結果(status="A" OR age=50 のデータ)
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "age" : 10, "status" : "A" }


大小比較を指定する(>演算子)

// SQL
SELECT * FROM users WHERE age > 25
// Mongo
db.users.find(
    {age: {$gt: 25}}
)
// 実行結果(age>25 のデータ)
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d56b5aa73f980c884bf53"), "user_id" : "def001", "age" : 30, "status" : "B" }


大小比較を指定する(>=演算子)

// SQL
SELECT * FROM users WHERE age >= 25
// Mongo
db.users.find(
    {age: {$gte: 25}}
)
// 実行結果(age>=25 のデータ)
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d56b5aa73f980c884bf53"), "user_id" : "def001", "age" : 30, "status" : "B" }


大小比較を指定する(<演算子)

// SQL
SELECT * FROM users WHERE age < 25
// Mongo
db.users.find(
    {age: {$lt: 25}}
)
// 実行結果(age<25 のデータ)
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "age" : 10, "status" : "A" }


大小比較を指定する(<=演算子)

// SQL
SELECT * FROM users WHERE age <= 25
// Mongo
db.users.find(
    {age: {$lte: 25}}
)
// 実行結果(age<=25 のデータ)
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "age" : 10, "status" : "A" }


LIKE検索を行う(前方後方一致)

// SQL
SELECT * FROM users WHERE user_id like "%bc%"
// Mongo
db.users.find(
    {user_id: /bc/}
)
// 実行結果(user_id like "%bc%" のデータ)
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }


LIKE検索を行う(後方一致)

// SQL
SELECT * FROM users WHERE user_id like "bc%"
// Mongo
db.users.find(
    {user_id: /^bc/}
)
// 実行結果(user_id like "bc%" のデータ)
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }


IN句で検索する

// SQL
SELECT * FROM users WHERE age IN (20, 45)
// Mongo
db.users.find(
    {age: {$in: [20, 45]}}
)
// 実行結果(user_id like "bc%" のデータ)
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }


DISTINCTを指定する

// SQL
SELECT DISTINCT status FROM users
// Mongo
db.users.distinct("status")
// 実行結果
[ "A", "B" ]


DISTINCT結果の件数を取得する

// SQL
SELECT COUNT(DISTINCT status) FROM users
// Mongo
db.users.distinct("status").length
// 実行結果
2


ソートを指定する(昇順)

// SQL
SELECT * FROM users ORDER BY user_id ASC
// Mongo
db.users.find({}).sort(
    {user_id: 1}
)
// 実行結果(ORDER BY user_id ASC のデータ)
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "age" : 10, "status" : "A" }
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }
{ "_id" : ObjectId("556d56b5aa73f980c884bf53"), "user_id" : "def001", "age" : 30, "status" : "B" }


ソートを指定する(降順)

// SQL
SELECT * FROM users ORDER BY user_id DESC
// Mongo
db.users.find({}).sort(
    {user_id: -1}
)
// 実行結果(ORDER BY user_id DESC のデータ)
{ "_id" : ObjectId("556d56b5aa73f980c884bf53"), "user_id" : "def001", "age" : 30, "status" : "B" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }
{ "_id" : ObjectId("556d6562aa73f980c884bf54"), "age" : 10, "status" : "A" }


件数を数える

// SQL
SELECT COUNT(*) FROM users
// Mongo
db.users.count()
// または
db.users.find().count()
// 実行結果
5


件数を数える(フィールド指定)

// SQL
SELECT COUNT(user_id) FROM users
// Mongo
db.users.count({user_id: {$exists: true}})
// または
db.users.find({user_id: {$exists: true}}).count()
// 実行結果
4


LIMIT句を指定する

// SQL
SELECT * FROM users LIMIT 1
// Mongo
db.users.findOne()
// または
db.users.find().limit(1)
// 実行結果
{ "_id" : ObjectId("556d5643aa73f980c884bf4f"), "user_id" : "abc001", "age" : 45, "status" : "A" }


LIMIT句でOFFSETを指定する

// SQL
SELECT * FROM users LIMIT 2 SKIP 1
// Mongo
db.users.find().limit(2).skip(1)
// 実行結果
{ "_id" : ObjectId("556d56b4aa73f980c884bf50"), "user_id" : "bcd001", "age" : 50, "status" : "A" }
{ "_id" : ObjectId("556d56b4aa73f980c884bf51"), "user_id" : "cde001", "age" : 20, "status" : "A" }


実行計画を確認する

// SQL
EXPLAIN SELECT * FROM users WHERE status = "A"
// Mongo
db.users.find({status: "A"}).explain()
// 実行結果
{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 4,
    "nscannedObjects" : 5,
    "nscanned" : 5,
    "nscannedObjectsAllPlans" : 5,
    "nscannedAllPlans" : 5,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "server" : "MyUser.local:27017",
    "filterSet" : false
}



参考資料

今回の記事を書くために以下を参考にしました。ありがとうございます。

SQL to MongoDB Mapping Chart — MongoDB Manual

はじめてのMongoDB | Slideshare


最後に

Mongoのfindは本当にいろいろな検索ができて便利ですね。ただこれらの情報がWeb上では少し断片的になっているなぁと思い、今後の自分のためにもまとめてみました。どなたかの何かの役に立てば幸いです。

最後になりますが本ブログでは、フロントエンドのネタを中心に情報を発信しています。気になった方はぜひ、RSSTwitterをフォローして頂けますと幸いです ^ ^。

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。