Transformers(3) - 質疑応答

今回は、Transformersを使って質疑応答を行います。

(Transformersのインストールは完了している想定となります。)

質疑応答

質疑応答では、コンテキスト質問からコンテキスト内に含まれる応答を抽出します。

ソースとしては、タスク名‘question-answering’を指定したパイプラインを作成し、コンテキストと質問を渡して応答を推論します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
from transformers import pipeline

# 質疑応答のパイプラインの準備
nlp = pipeline('question-answering')

# コンテキスト
context = 'Huggingface Transformers is a deep learning framework provided by Huggingface that specializes in natural language processing. It supports both TensorFlow and PyTorch. You can use deep learning to solve natural language processing tasks such as text classification, question answering, and summary.'

# 質問
question = 'What is a natural language processing task?'

# 推論
print(nlp(question=question, context=context))

実行結果は下記の通りです。

[実行結果]

1
{'score': 0.6564476490020752, 'start': 245, 'end': 297, 'answer': 'text classification, question answering, and summary'}

スコア65で、テキスト分類、質疑応答、要約という結果になりました。

正しい応答になっていると思います。


次回は、要約を行います。

Transformers(2) - インストール/テキスト分類

今回は、Transformersのインストールとテキスト分類を行います。

Transformersのインストール

Transformersのインストールを行うためには次のコマンドを実行します。

実行環境としてはGoogle Colaboratoryを想定しています。

[Google Colaboratory]

1
!pip install transformers[ja]==4.4.2

次のような実行結果が表示されればインストールは成功しています。

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Collecting transformers[ja]==4.4.2
Downloading transformers-4.4.2-py3-none-any.whl (2.0 MB)
|████████████████████████████████| 2.0 MB 13.1 MB/s
Requirement already satisfied: filelock in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (3.0.12)
Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (21.0)
Requirement already satisfied: regex!=2019.12.17 in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (2019.12.20)
Requirement already satisfied: importlib-metadata in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (4.8.1)
Requirement already satisfied: numpy>=1.17 in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (1.19.5)
Collecting tokenizers<0.11,>=0.10.1
Downloading tokenizers-0.10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (3.3 MB)
|████████████████████████████████| 3.3 MB 56.6 MB/s
Requirement already satisfied: tqdm>=4.27 in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (4.62.2)
Collecting sacremoses
Downloading sacremoses-0.0.45-py3-none-any.whl (895 kB)
|████████████████████████████████| 895 kB 55.7 MB/s
Requirement already satisfied: requests in /usr/local/lib/python3.7/dist-packages (from transformers[ja]==4.4.2) (2.23.0)
Collecting fugashi>=1.0
Downloading fugashi-1.1.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (490 kB)
|████████████████████████████████| 490 kB 60.5 MB/s
Collecting ipadic<2.0,>=1.0.0
Downloading ipadic-1.0.0.tar.gz (13.4 MB)
|████████████████████████████████| 13.4 MB 212 kB/s
Collecting unidic>=1.0.2
Downloading unidic-1.0.3.tar.gz (5.1 kB)
Collecting unidic-lite>=1.0.7
Downloading unidic-lite-1.0.8.tar.gz (47.4 MB)
|████████████████████████████████| 47.4 MB 79 kB/s
Requirement already satisfied: wasabi<1.0.0,>=0.6.0 in /usr/local/lib/python3.7/dist-packages (from unidic>=1.0.2->transformers[ja]==4.4.2) (0.8.2)
Requirement already satisfied: plac<2.0.0,>=1.1.3 in /usr/local/lib/python3.7/dist-packages (from unidic>=1.0.2->transformers[ja]==4.4.2) (1.1.3)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (3.0.4)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (1.24.3)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (2021.5.30)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests->transformers[ja]==4.4.2) (2.10)
Requirement already satisfied: typing-extensions>=3.6.4 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->transformers[ja]==4.4.2) (3.7.4.3)
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->transformers[ja]==4.4.2) (3.5.0)
Requirement already satisfied: pyparsing>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->transformers[ja]==4.4.2) (2.4.7)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers[ja]==4.4.2) (1.15.0)
Requirement already satisfied: joblib in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers[ja]==4.4.2) (1.0.1)
Requirement already satisfied: click in /usr/local/lib/python3.7/dist-packages (from sacremoses->transformers[ja]==4.4.2) (7.1.2)
Building wheels for collected packages: ipadic, unidic, unidic-lite
Building wheel for ipadic (setup.py) ... done
Created wheel for ipadic: filename=ipadic-1.0.0-py3-none-any.whl size=13556723 sha256=868f02ff1674a53b19d8180bdf7a9473a57ab3be9cb1551291fdcb03bfb98bc5
Stored in directory: /root/.cache/pip/wheels/33/8b/99/cf0d27191876637cd3639a560f93aa982d7855ce826c94348b
Building wheel for unidic (setup.py) ... done
Created wheel for unidic: filename=unidic-1.0.3-py3-none-any.whl size=5506 sha256=8977d77c05cd5ec120e9f048171cc7fe4804c6191cb8c3dc209a1eae232c6aa8
Stored in directory: /root/.cache/pip/wheels/23/30/0b/128289fb595ef4117d2976ffdbef5069ef83be813e88caa0a6
Building wheel for unidic-lite (setup.py) ... done
Created wheel for unidic-lite: filename=unidic_lite-1.0.8-py3-none-any.whl size=47658836 sha256=05af03831b7babce0692a95538db2a5616e083838fd8a98d6336cdf8e6f9a009
Stored in directory: /root/.cache/pip/wheels/de/69/b1/112140b599f2b13f609d485a99e357ba68df194d2079c5b1a2
Successfully built ipadic unidic unidic-lite
Installing collected packages: tokenizers, sacremoses, unidic-lite, unidic, transformers, ipadic, fugashi
Successfully installed fugashi-1.1.1 ipadic-1.0.0 sacremoses-0.0.45 tokenizers-0.10.3 transformers-4.4.2 unidic-1.0.3 unidic-lite-1.0.8

テキスト分類

テキスト分類は、テキストを事前に定義されたカテゴリに分類する処理となります。

今回は文章を「ポジティブ」か「ネガティブ」かに分類してみます。

タスク名‘sentiment-analysis’を指定したパイプラインを作成し、そのパイプラインに任意の文章を渡します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
from transformers import pipeline

# テキスト分類のパイプラインを準備
nlp = pipeline('sentiment-analysis')

# テキスト
text = 'This movie was very interesting.'

# 推論
print(nlp(text))

[実行結果]

1
2
3
4
5
6
7
8
9
Downloading: 100%
629/629 [00:00<00:00, 10.1kB/s]
Downloading: 100%
268M/268M [00:06<00:00, 45.4MB/s]
Downloading: 100%
232k/232k [00:00<00:00, 266kB/s]
Downloading: 100%
48.0/48.0 [00:00<00:00, 850B/s]
[{'label': 'POSITIVE', 'score': 0.9997621178627014}]

スコア99以上で‘POSITIVE’な文章であると判断できました。


少し文章を変更して再度テキスト分類を行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
from transformers import pipeline

# テキスト分類のパイプラインを準備
nlp = pipeline('sentiment-analysis')

# テキスト
text = 'This movie was very silly.'

# 推論
print(nlp(text))

[実行結果]

1
[{'label': 'NEGATIVE', 'score': 0.9983341693878174}]

スコア99以上で‘NEGATIVE’な文章であると判断できました。

次回は、質問応答を行います。

Transformers(1) - 概要

Transformersは、世界中で使われているデファクトスタンダードな自然言語処理の深層学習フレームワークです。

このフレームワークを使うことで、最先端の自然言語処理を体験することができます。

Transformersの概要

Transformersは、PyTorchTensorflowの両方に対応していて、深層学習を使って下記のような自然言語処理を行うことができます。

  • テキスト分類
  • 質疑応答
  • 要約
  • テキスト生成
  • 言語モデル

モデルアーキテクチャ

次のような最先端のモデルアーキテクチャを提供しています。

  • BERT
  • GPT-2
  • T5

事前学習モデル

様々な事前学習モデルが提供されており、最先端の自然言語処理アルゴリズムを容易に試すことができます。

提供されている事前学習モデルは以下のサイトで確認できます。

提供されている事前学習モデル - https://huggingface.co/transformers/pretrained_models.html


またコミュニティで提供されている学習済みモデルもあります。

The All community building the future - https://huggingface.co/models


次回は、Transformersのインストールとテキスト分類を行います。

MongoDB(36) - 一括処理(Bulk)⑤一括削除

今回は、一括削除を行います。

一括削除処理(remove)

順次処理で一括削除を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. removeクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> var bulk = db.member.initializeOrderedBulkOp()

> bulk.find({LastName:'武元'}).removeOne()
> bulk.find({LastName:'松田'}).removeOne()
> bulk.find({LastName:'加藤'}).removeOne()

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 3,
"upserted" : [ ]
})

> db.member.find()
{ "_id" : ObjectId("613e8ff0d1340480894d324d"), "LastName" : "伊藤", "age" : 43 }

3件のドキュメントを一括で削除することができました。

Pythonで操作

上記の処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pymongo
from pymongo import MongoClient
from pymongo import DeleteOne
from pymongo.errors import BulkWriteError

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 一括入れ替え
requests = [
DeleteOne({'LastName': '武元'}),
DeleteOne({'LastName': '松田'}),
DeleteOne({'LastName': '加藤'})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 入れ替え内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

次回からは、検索を高速化するためのインデックに関する操作を行います。

MongoDB(35) - 一括処理(Bulk)④一括登録/一括更新処理(upsert)

今回は、一括登録/一括更新処理(upsert)を行います。

一括登録/一括更新処理(upsert)

順次処理で一括登録/一括更新処理(upsert)を行います。

upsert処理では該当するデータが存在する場合は更新を行い、該当するデータがない場合は登録を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. upsertクエリーを設定。(3~6行目)
    前半の3件が更新処理で、最後の1件が登録処理になります。
  3. 一括実行(Bulk実行)。(8行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
> var bulk = db.member.initializeOrderedBulkOp()

> bulk.find({LastName:'武元'}).upsert().updateOne({$set:{age:12}}) // 更新
> bulk.find({LastName:'松田'}).upsert().updateOne({$set:{age:23}}) // 更新
> bulk.find({LastName:'加藤'}).upsert().updateOne({$set:{age:33}}) // 更新
> bulk.find({LastName:'伊藤'}).upsert().updateOne({$set:{age:43}}) // 追加

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 1,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [
{
"index" : 3,
"_id" : ObjectId("613e8ff0d1340480894d324d")
}
]
})

> db.member.find()
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b87"), "LastName" : "武元", "FirstName" : "ゆい", "age" : 12 }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b88"), "LastName" : "松田", "FirstName" : "りな", "age" : 23 }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b89"), "LastName" : "加藤", "FirstName" : "しほ", "age" : 33 }
{ "_id" : ObjectId("613e8ff0d1340480894d324d"), "LastName" : "伊藤", "age" : 43 }

前半の3ドキュメントに関してはデータが存在していたので、既存データにageフィールドが追加されています。

最後の1ドキュメントに関してはデータが存在していなかったため、新規ドキュメントとしてデータが追加されています。

Pythonで操作

上記の処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import pymongo
from pymongo import MongoClient
from pymongo import UpdateOne
from pymongo.errors import BulkWriteError

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 一括入れ替え
requests = [
UpdateOne({'LastName': '武元'},{'$set':{'age':12}}, upsert=True),
UpdateOne({'LastName': '松田'},{'$set':{'age':23}}, upsert=True),
UpdateOne({'LastName': '加藤'},{'$set':{'age':33}}, upsert=True),
UpdateOne({'LastName': '伊藤'},{'$set':{'age':43}}, upsert=True)
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 入れ替え内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

Pythonでupsert処理を行う場合は、UpdateOneを使ってupsert=Trueオプションを追加します。


次回は、一括削除処理(remove)を行います。

MongoDB(34) - 一括処理(Bulk)③一括入れ替え

今回は、一括入れ替え処理を行います。

一括入れ替え

順次処理で一括入れ替えを行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. replaceクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> var bulk = db.member.initializeOrderedBulkOp()

> bulk.find({name:"武元"}).replaceOne({LastName:"武元", FirstName:"ゆい"})
> bulk.find({name:"松田"}).replaceOne({LastName:"松田", FirstName:"りな"})
> bulk.find({name:"加藤"}).replaceOne({LastName:"加藤", FirstName:"しほ"})

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [ ]
})
> db.member.find()
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b87"), "LastName" : "武元", "FirstName" : "ゆい" }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b88"), "LastName" : "松田", "FirstName" : "りな" }
{ "_id" : ObjectId("613e8e9a0fb0f3e6cf9e2b89"), "LastName" : "加藤", "FirstName" : "しほ" }

問題なく3つのドキュメントの入れ替えを行うことができました。

Pythonで操作

上記の処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pymongo
from pymongo import MongoClient
from pymongo import ReplaceOne
from pymongo.errors import BulkWriteError

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 一括入れ替え
requests = [
ReplaceOne({'name': '武元'},{'LastName':'武元', 'FirstName':'ゆい'}),
ReplaceOne({'name': '松田'},{'LastName':'松田', 'FirstName':'りな'}),
ReplaceOne({'name': '加藤'},{'LastName':'加藤', 'FirstName':'しほ'})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 入れ替え内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

ReplaceOneの第1引数には検索条件を指定し、第2引数には入れ替えるドキュメントの内容を設定します。

次回は、一括登録/一括更新処理(upsert)を行います。

MongoDB(33) - 一括処理(Bulk)②一括更新

今回は、一括更新(Bulk)に関する操作を行います。

一括更新

順次処理で一括更新を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()の代わりにinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. updateクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> var bulk = db.member.initializeOrderedBulkOp()    //順次処理

> bulk.find({name:'武元'}).updateOne({$set:{age:11}})
> bulk.find({name:'松田'}).updateOne({$set:{age:21}})
> bulk.find({name:'加藤'}).updateOne({$set:{age:31}})

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [ ]
})

> db.member.find()
{ "_id" : ObjectId("613e8c820fb0f3e6cf9e2b81"), "name" : "武元", "age" : 11 }
{ "_id" : ObjectId("613e8c820fb0f3e6cf9e2b82"), "name" : "松田", "age" : 21 }
{ "_id" : ObjectId("613e8c820fb0f3e6cf9e2b83"), "name" : "加藤", "age" : 31 }

問題なく3つのドキュメントの年齢(age)を更新することができました。

Pythonで操作

上記の処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pymongo
from pymongo import MongoClient
from pymongo import UpdateOne
from pymongo.errors import BulkWriteError

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 一括更新
requests = [
UpdateOne({'name':'武元'}, {'$set':{'age':11}}),
UpdateOne({'name':'松田'}, {'$set':{'age':21}}),
UpdateOne({'name':'加藤'}, {'$set':{'age':31}})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 更新内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

次回は、一括入れ替え処理を行います。

MongoDB(32) - 一括処理(Bulk)①一括登録

今回から、一括処理(Bulk)に関する操作を行っていきます。

一括処理(Bulk)とは

大量にinsertやupdateを行う場合、一括処理(Bulk)を使うとまとめて処理を行うことができるため速く実行することができます

一括処理(Bulk)には、下記の2種類があります。

  1. 順次処理
    登録の順番に意味がある場合に使用します。
    前の処理が終わってから次の処理を行うため、2.並列処理よりも処理は遅くなります、
  2. 並列処理
    順番に関係なく処理を行います。
    そのため1.順次処理よりも速く処理が終了します。

一括登録

順次処理で一括登録を行います。

(並列処理で実行したい場合は、initializeOrderedBulkOp()ではなくinitializeUnorderedBulkOp()を使います。)

処理の詳細は以下の通りです。

  1. Bulk実行タイプを設定。(1行目)
  2. insertクエリーを設定。(3~5行目)
  3. 一括実行(Bulk実行)。(7行目)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> var bulk = db.member.initializeOrderedBulkOp()  //順次処理

> bulk.insert({name:"武元", age:10})
> bulk.insert({name:"松田", age:20})
> bulk.insert({name:"加藤", age:30})

> bulk.execute()
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 3,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})

> db.member.find()
{ "_id" : ObjectId("613e728c0fb0f3e6cf9e2b7e"), "name" : "武元", "age" : 10 }
{ "_id" : ObjectId("613e728c0fb0f3e6cf9e2b7f"), "name" : "松田", "age" : 20 }
{ "_id" : ObjectId("613e728c0fb0f3e6cf9e2b80"), "name" : "加藤", "age" : 30 }

問題なく3つのドキュメントを追加することができました。

Pythonで操作

上記の処理をPythonで行うと、次のようになります。

3~4行目に新たにimport文を追加していますのでご注意下さい。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import pymongo
from pymongo import MongoClient
from pymongo import InsertOne
from pymongo.errors import BulkWriteError

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 一括更新
requests = [
InsertOne({'name':'武元', 'age':10}),
InsertOne({'name':'松田', 'age':20}),
InsertOne({'name':'加藤', 'age':30})
]

try:
db1.member.bulk_write(requests) # 順次処理
# db.member.bulk_write(requests, ordered=False) # 並列処理
except BulkWriteError as bwe:
pprint(bwe.details)

# 登録内容の確認
docs = db1.member.find()
for doc in docs:
print(doc)

次回は、一括更新処理を行います。

MongoDB(31) - 集計処理(aggregate)⑫集計結果のソート/表示件数制限/取得開始位置の指定

今回は、集計結果のソート/表示件数制限/取得開始位置の指定を行います。

サンプルデータ

以前用意した会社の部、課、従業員データを使用します。

集計処理(aggregate)①データ準備 - https://ailog.site/2021/09/02/2021/0902/

集計結果のソート

集計結果をソートしてみます。

集計結果のソートには$sortを使います。

[Mongoシェル]

1
2
3
4
5
6
7
8
> db.employee.aggregate([
{$group:{_id:"$k_id", max_salary:{$max: "$salary"}}},
{$sort:{max_salary:1}} // 1:昇順 -1:降順
])
{ "_id" : "ka4", "max_salary" : 120000 }
{ "_id" : "ka2", "max_salary" : 250000 }
{ "_id" : "ka1", "max_salary" : 400000 }
{ "_id" : "ka3", "max_salary" : 550000 }

課ごとの最大給料に関して、昇順でソートすることができました。

集計結果の表示件数制限

集計結果の表示件数を制限します。

集計結果の表示件数制限には$limitを使います。

[Mongoシェル]

1
2
3
4
5
6
> db.employee.aggregate([
{$group:{_id:"$k_id", max_salary:{$max: "$salary"}}},
{$sort:{max_salary:1}},
{$limit: 1}
])
{ "_id" : "ka4", "max_salary" : 120000 }

課ごとの最大給料に関して、表示件数を1件に制限することができました。

集計結果の取得開始位置の指定

集計結果の取得開始位置を指定します。

集計結果の表示開始位置を指定するためには$skipを使用します。

[Mongoシェル]

1
2
3
4
5
6
7
8
> db.employee.aggregate([
{$group:{_id:"$k_id", max_salary:{$max: "$salary"}}},
{$sort:{max_salary:1}},
{$skip: 1}
])
{ "_id" : "ka2", "max_salary" : 250000 }
{ "_id" : "ka1", "max_salary" : 400000 }
{ "_id" : "ka3", "max_salary" : 550000 }

課ごとの最大給料に関して、表示開始位置を2つめからとすることができました。

$skipに指定するインデックスは0から始まりますので、1を指定した場合は2つめの集計結果から表示されることになります。


$sort$limit$skip は組み合わせて実行することが可能ですが、上から順番に実行されるので順番には気を付ける必要があります。

Pythonで操作

上記の集計処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import pymongo
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 集計結果のソート
docs = db1.employee.aggregate([
{'$group':{'_id':'$k_id', 'max_salary':{'$max': '$salary'}}},
{'$sort':{'max_salary':1}} # 1:昇順 -1:降順
])
for doc in docs:
print(doc)

# 集計結果の表示件数制限
docs = db1.employee.aggregate([
{'$group':{'_id':'$k_id', 'max_salary':{'$max': '$salary'}}},
{'$sort':{'max_salary':1}},
{'$limit': 1}
])
for doc in docs:
print(doc)


# 集計結果の取得開始位置の指定
docs = db1.employee.aggregate([
{'$group':{'_id':'$k_id', 'max_salary':{'$max': '$salary'}}},
{'$sort':{'max_salary':1}},
{'$skip': 1}
])
for doc in docs:
print(doc)

次回からは、一括高速処理(Bulk)を行います。

MongoDB(30) - 集計処理(aggregate)⑪複数コレクションの結合

今回は、複数コレクションの結合を行います。

サンプルデータ

以前用意した会社の部、課、従業員データを使用します。

集計処理(aggregate)①データ準備 - https://ailog.site/2021/09/02/2021/0902/

複数コレクションの結合

1つのコレクションから複数のコレクションを同時に結合します。

コレクションの結合方法は下記の通りです。

  • 従業員コレクション(employee)と課コレクション(division)を結合
    結合キーは課ID(k_id)
  • 従業員コレクション(employeeと役職コレクション(position)を結合
    結合キーは役職ID(p_id)

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> db.employee.aggregate([
{$lookup:{
from: "division",
localField: "k_id",
foreignField: "k_id",
as: "division_docs"
}},
{$lookup:{
from: "position",
localField: "p_id",
foreignField: "p_id",
as: "position_docs"
}}
])
{ "_id" : ObjectId("612f07f568110fe533ed9d21"), "e_id" : "emp001", "k_id" : "ka1", "p_id" : "po1", "name" : "高山", "age" : 31, "salary" : 400000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d19"), "k_id" : "ka1", "b_id" : "bu1", "name" : "総務課" } ], "position_docs" : [ { "_id" : ObjectId("612f07d768110fe533ed9d1d"), "p_id" : "po1", "name" : "社長" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d22"), "e_id" : "emp002", "k_id" : "ka2", "p_id" : "po2", "name" : "生駒", "age" : 37, "salary" : 250000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1a"), "k_id" : "ka2", "b_id" : "bu2", "name" : "企画課" } ], "position_docs" : [ { "_id" : ObjectId("612f07d768110fe533ed9d1e"), "p_id" : "po2", "name" : "部長" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d23"), "e_id" : "emp003", "k_id" : "ka3", "p_id" : "po3", "name" : "嘉喜", "age" : 23, "salary" : 200000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1b"), "k_id" : "ka3", "b_id" : "bu3", "name" : "開発1課" } ], "position_docs" : [ { "_id" : ObjectId("612f07d768110fe533ed9d1f"), "p_id" : "po3", "name" : "課長" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d24"), "e_id" : "emp004", "k_id" : "ka4", "p_id" : "po4", "name" : "与田", "age" : 33, "salary" : 100000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1c"), "k_id" : "ka4", "b_id" : "bu3", "name" : "開発2課" } ], "position_docs" : [ { "_id" : ObjectId("612f07d768110fe533ed9d20"), "p_id" : "po4", "name" : "一般社員" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d25"), "e_id" : "emp005", "k_id" : "ka3", "p_id" : "po4", "name" : "松田", "age" : 35, "salary" : 550000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1b"), "k_id" : "ka3", "b_id" : "bu3", "name" : "開発1課" } ], "position_docs" : [ { "_id" : ObjectId("612f07d768110fe533ed9d20"), "p_id" : "po4", "name" : "一般社員" } ] }
{ "_id" : ObjectId("612f07f568110fe533ed9d26"), "e_id" : "emp006", "k_id" : "ka4", "p_id" : "po4", "name" : "菅井", "age" : 45, "salary" : 120000, "division_docs" : [ { "_id" : ObjectId("612f07b568110fe533ed9d1c"), "k_id" : "ka4", "b_id" : "bu3", "name" : "開発2課" } ], "position_docs" : [ { "_id" : ObjectId("612f07d768110fe533ed9d20"), "p_id" : "po4", "name" : "一般社員" } ] }

従業員コレクションから、課コレクションと役職コレクションを結合することができました。

表示フィールドの絞り込み

複数コレクションの結合を行った結果に対して、$projectを使って表示フィールドを絞り込みます。

オブジェクトID(_id)を非表示にし、従業員ID(e_id)・従業員名・課の名称・役職名を表示します。

また同時にunwindを使い、配列をオブジェクト型に展開します。

[Mongoシェル]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
> db.employee.aggregate([
{$lookup:{
from: "division",
localField: "k_id",
foreignField: "k_id",
as: "division_docs"
}},
{$lookup:{
from: "position",
localField: "p_id",
foreignField: "p_id",
as: "position_docs"
}},
{$project:{
"_id": 0,
"e_id": 1,
"name": 1,
"division_docs.name": 1,
"position_docs.name": 1
}},
{$unwind: "$division_docs"}, // 課コレクションの展開
{$unwind: "$position_docs"} // 役職コレクションの展開
])
{ "e_id" : "emp001", "name" : "高山", "division_docs" : { "name" : "総務課" }, "position_docs" : { "name" : "社長" } }
{ "e_id" : "emp002", "name" : "生駒", "division_docs" : { "name" : "企画課" }, "position_docs" : { "name" : "部長" } }
{ "e_id" : "emp003", "name" : "嘉喜", "division_docs" : { "name" : "開発1課" }, "position_docs" : { "name" : "課長" } }
{ "e_id" : "emp004", "name" : "与田", "division_docs" : { "name" : "開発2課" }, "position_docs" : { "name" : "一般社員" } }
{ "e_id" : "emp005", "name" : "松田", "division_docs" : { "name" : "開発1課" }, "position_docs" : { "name" : "一般社員" } }
{ "e_id" : "emp006", "name" : "菅井", "division_docs" : { "name" : "開発2課" }, "position_docs" : { "name" : "一般社員" } }

コレクションを結合した結果から、想定通りのフィールドを表示することができました。

Pythonで操作

上記の集計処理をPythonで行うと、次のようになります。

[ソースコード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import pymongo
from pymongo import MongoClient

# MongoDB操作用のインスタンスを作成
client = MongoClient() # [IPとポートを指定する場合] MongoClient('10.200.243.203', 27017')

# データベースの取得
db1 = client.db1

# 複数コレクションの結合
docs = db1.employee.aggregate([
{'$lookup':{
'from': 'division',
'localField': 'k_id',
'foreignField': 'k_id',
'as': 'division_docs'
}},
{'$lookup':{
'from': 'position',
'localField': 'p_id',
'foreignField': 'p_id',
'as': 'position_docs'
}}
])
for doc in docs:
print(doc)

# 表示フィールドの絞り込み
docs = db1.employee.aggregate([
{'$lookup':{
'from': 'division',
'localField': 'k_id',
'foreignField': 'k_id',
'as': 'division_docs'
}},
{'$lookup':{
'from': 'position',
'localField': 'p_id',
'foreignField': 'p_id',
'as': 'position_docs'
}},
{'$project':{
'_id': 0,
'e_id': 1,
'name': 1,
'division_docs.name': 1,
'position_docs.name': 1
}},
{'$unwind': '$division_docs'}, # 課コレクションの展開
{'$unwind': '$position_docs'} # 役職コレクションの展開
])
for doc in docs:
print(doc)

次回は、集計結果のソート/表示件数制限/取得開始位置の指定を行います。


Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×