読者です 読者をやめる 読者になる 読者になる

くろねこ日記

ソフトウェアに関する技術メモが多いです.

MongoEngineつかってみた

はじめに

前回MongoDBをつかってみたという記事を載せました.その記事ではpyMongoを利用したMongoDBの操作を紹介しましたが,今日はPython上でMongoDBをOSMとして扱うことのできるMongoEngineの紹介をします.

MongoEngineインストール

インストールは簡単

pip install mongoengine

のみです.

使い方

学生情報を扱うデータベースを例に話を進めていきます. まずは,ドキュメントの追加と参照について説明します

追加と参照

  • データベース名:studentinfo

  • クラス名: Student(学生情報を扱う)

    • 要素:Name(学生名)

    • 要素:Number(学生番号)

import mongoengine

mongoengine.connect("studentinfo")

class Student(mongoengine.Document):
    Name = mongoengine.StringField()
    Number = mongoengine.IntField()

#DBの初期化を行なう(ブログの内容には直接関係しない)
Student.drop_collection()

db=Student()
db.Name="Taro"
db.Number=1
db.save()

for data in Student.objects:
    print data.Name
    print data.Number

出力だけならこれだけです.

もし特定のデータ(Number1にしましょう)だけ取りだしたいなら

import mongoengine

mongoengine.connect("studentinfo")

class Student(mongoengine.Document):
    Name = mongoengine.StringField()
    Number = mongoengine.IntField()

#DBの初期化を行なう(ブログの内容には直接関係しない)
Student.drop_collection()

db=Student()
db.Name="Taro"
db.Number=1
db.save()

for data in Student.objects(Number=1):
    print data.Name
    print data.Number

のようにすればNumber1のデータだけが表示されます

親子関係にあるデータベース

では次はMongoEngineで親子関係にあるデータベースを組んでみましょう. 例題として先程のStudentの加えて試験の結果を子とします.

  • データベース名:studentinfo

  • クラス名:Student

    • 要素:Name(学生名)

    • 要素:Number(学生番号)

  • クラス名:Math

    • 要素:score(点数)
  • クラス名:Science

    • 要素:score(点数)
  • クラス名:English

    • 要素:score(点数)

とします.

この場合はStudentから各科目(Math,Science,English)を呼べるようにします.

import mongoengine

mongoengine.connect("studentinfo")

class Math(mongoengine.Document):
    score = mongoengine.IntField()

class English(mongoengine.Document):
    score = mongoengine.IntField()

class Student(mongoengine.Document):
    name = mongoengine.StringField()
    math = mongoengine.ReferenceField("Math")
    english = mongoengine.ReferenceField("English")

こうします.実際にStudentを経由してMathやEnglishのデータを書き込むには 次のようにします.ここでは[学生名taro,数学100点,英語50点]というデータと[学生名jiro,数学70点,英語80点]として書いていきます

taro = Student()
math = Math()
english = English()
math.score=100
math.save()
english.score=50
english.save()
taro.name="taro"
taro.math=math
taro.english=english
taro.save()

jiro = Student()
math = Math()
english = English()
math.score=70
math.save()
english.score=80
english.save()
jiro.name="jiro"
jiro.math=math
jiro.english=english
jiro.save()

とします.mathとenglishそれぞれのインスタンスに各点数を代入したのちstudentのクラス変数に渡してますね.

値を取り出すには

for student in Student.objects:
     print student.name
     print student.math.score
     print student.english.score

のようにします. おそらく

taro
100
50
jiro
70
80

と出力されるはずです.

もし複数件入力されており,名前が"taro"だけのデータが欲しいときには

for student in Student.objects(name="taro"):
     print student.name
     print student.math.score
     print student.english.score     

結果

taro
100
50

のようにobjectsにname="taro"のように指定するだけです.

ここの部分を一つのコードにまとめると

import mongoengine

mongoengine.connect("studentinfo")

#クラスの定義
class Math(mongoengine.Document):
    score = mongoengine.IntField()

class English(mongoengine.Document):
    score = mongoengine.IntField()

class Student(mongoengine.Document):
    name = mongoengine.StringField()
    math = mongoengine.ReferenceField("Math")
    english = mongoengine.ReferenceField("English")

#DBの初期化を行なう(ブログの内容には直接関係しない)
Student.drop_collection()

#taroとjiroのドキュメントを追加
taro = Student()
math = Math()
english = English()
math.score=100
math.save()
english.score=50
english.save()
taro.name="taro"
taro.math=math
taro.english=english
taro.save()
jiro = Student()
math = Math()
english = English()
math.score=70
math.save()
english.score=80
english.save()
jiro.name="jiro"
jiro.math=math
jiro.english=english
jiro.save()

#Studentクラスに書かれているドキュメントをすべて取得
for student in Student.objects:
     print student.name
     print student.math.score
     print student.english.score

#taroのドキュメントのみ取得
for student in Student.objects(name="taro"):
     print student.name
     print student.math.score
     print student.english.score

上書き

次に既存のデータを上書きしたときについてですが,上記のjiroをsaburoに変更してみましょう.

jiro = Student.objects(name="jiro")
jiro.update(set__name="saburo")

のようにobjectsでデータを抜きだしてからupdate文で更新します. 更新の際にはset__のようにqueryを指定することができます.set__ query以外にもpush__ , unset__ , pull__などがあります 詳しくはこちらをお読みください(http://mongoengine-odm.readthedocs.org/guide/querying.html) .

まとめ

MongoEngineでデータの追加や参照,更新についてまとめました.