私はGoにとても慣れていません。 mGoの例で見たものから、コレクションをクエリしてそこから読み取るには、構造体に返されるデータを事前に定義する必要があります。
type Person struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string
Phone string
Timestamp time.Time
}
PHPでは、ドキュメントは配列に割り当てられていました。 1つのレコードに完全に異なるキーのセット(名前や電話は含まれていないが電子メールは含まれている)があり、事前定義されたクラス/構造体/変数を設定せずに直接アクセスできるため、これは完璧でした。
Go/mGoで同じことをする方法はありますか?
これを処理する方法は複数あります。
マップの使用:
var m bson.M
err := collection.Find(nil).One(&m)
check(err)
for key, value := range m {
fmt.Println(key, value)
}
Mgoに関する限り、 bson.M について特別なことは何もないことに注意してください。ただのmap[string]interface{}
タイプ。値タイプが異なっていても、独自のマップタイプを定義し、mgoで使用できます。
ドキュメントスライスの使用:
bson.D は、mgoに内部的に認識されているスライスであり、より効率的なメカニズムを提供するためと、MongoDBで使用されるキーの順序を保持する方法を提供するために存在します。状況(たとえば、インデックスを定義する場合)。
例えば:
var d bson.D
err := collection.Find(nil).One(&d)
check(err)
for i, elem := range d {
fmt.Println(elem.Name, elem.Value)
}
インラインマップフィールドの使用
,inline
bson flag マップフィールドでも使用できるので、ケーキを持って食べることもできます。つまり、構造体を使用できるため、既知のフィールドの操作が便利であると同時に、インラインマップを介して未知のフィールドを処理できます。
例えば:
type Person struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string
Phone string
Extra bson.M `bson:",inline"`
}
すべてを地図に保存できます。 mgo/bson
パッケージは任意のデータを格納するために使用できるbson.M
データ型を提供し、MongoDBは強力なスキーマを強制しないため、mgo
は内部でbson.M
型を使用します全てにおいて。
データを表示するだけの場合は、bson.M
を使用しても問題ありませんが、データの操作を開始したら、代わりに構造体の使用を検討する必要があります。そうしないと、プログラムに多くの型アサーションが必要になります。たとえば、ドキュメントのタイトル(result["title"]
)を大文字で印刷するとします。 bson.M
だけを使用すると、コードは次のようになります。
// is there a title attribute?
if title, ok := result["title"]; ok {
// is it a string? (and not another map or integer or something else)
if titleStr, ok := title.(string); ok {
// ok, it is a string
fmt.Println("Title: ", strings.ToUpper(titleStr))
}
}
mgo
にデータを構造体に変換させると、プログラムがはるかに読みやすくなり、保守が容易になります。次に、同じコードは次のようになります。
fmt.Println(strings.ToUpper(result.Title))
通常、処理するドキュメントのタイプごとに1つの構造体タイプ(つまり、「ユーザー」用に1つのタイプ、「ブログ投稿」用に別のタイプなど)を定義し、アクセスする可能性のあるすべての属性を含みます。ユーザードキュメントに電子メールアドレスが割り当てられていない場合は、デコード時に空の文字列(またはより一般的にはゼロ値)が返されます。