web-dev-qa-db-ja.com

mongodbドキュメントのIDタイプとして文字列を使用できますか?

私はmongodbを処理するためにJava/morphiaを使用しています。デフォルトのObjectIdは、Javaレイヤーから使用するのはあまり便利ではありません。ObjectIdを使用してキー生成プロセスを維持しながら、それを文字列型にしたいと思います。たとえば、_id = new ObjectId.toString()です。

このようにして副作用があるかどうか知りたいのですが?たとえば、データベースのパフォーマンスに影響したり、何らかの方法でキーの競合を引き起こしたりしますか?シャーディング環境に影響しますか?.

15
Gelin Luo

__id_フィールドには任意のタイプの値を使用できます(配列を除く)。 ObjectIdを使用しないことを選択した場合、何らかの方法で値の一意性を保証する必要があります(ObjectIdを文字列にキャストすることで実現します)。重複したキーを挿入しようとすると、エラーが発生し、対処する必要があります。

同じ_idを持つ2つのドキュメントを異なるシャードに挿入しようとすると、シャードクラスターにどのような影響があるかわかりません。私はそれがあなたに挿入を許すと思うが、これは後であなたを噛むでしょう。 (私はこれをテストする必要があります)。

とはいえ、_id = (new ObjectId).toString()を使用しても問題はありません。

22

ObjectIdをJSONに変換するときに問題が発生したため、実際には同じことを行いました。

それから私は次のようなことをしました

@Id
private String id;
public String getId() {
    return id();
}
public void setId(String id) {
    this.id = id;
}

そして、私が以前に挿入されたドキュメントを更新することを決定するまですべてがうまくいきました。私がオブジェクトをJSON経由でページに送信し、JSONポストによって同じ更新されたオブジェクトを受信し、データストアの代わりにデータストアから保存機能を使用したとき以前のデータを更新すると、すでにあるドキュメントを更新する代わりに、新しいドキュメントが挿入されました。

最悪の場合、新しいドキュメントのIDは以前に挿入されたものと同じであり、不可能だと思っていました。

とにかく、私はプライベートオブジェクトをObjectIDとして設定し、get setを文字列のままにしただけで、期待どおりに機能しました。

@Id
private ObjectId id;
public String getId() {
    return id.toString();
}
public void setId(String id) {
    this.id = new ObjectId(id);
}
5
Destino

はい、文字列を_idとして使用できます。

(ドキュメント内で)当然のことながら、適切な一意のキーである値を持っている場合にのみお勧めします。このデザインは、「xxxxyyyy」という形式の文字列ジオタグが存在する1つのコレクションで使用しました。この一意のドキュメントごとのフィールドは、ドキュメントに含まれる必要がありましたandそれにインデックスを作成する必要がありました...それで、キーとして使用しないのはなぜですか? (これにより、MondoDBは自然に "_id"にインデックスを作成するため、追加のキーと値のペアを1つ回避し、コレクションの2番目のインデックスを回避しました。コレクションのサイズを考えると、これらの両方により、かなりの領域を節約できます。)

ただし、質問のトーン(「ObjectIDはあまり便利ではない」)から、文字列を使用する唯一の理由が、ObjectIDを適切に管理する方法を考え出すことに煩わされたくない場合は... dあなたの頭をそれらの周りに置くことはあなたの時間の価値があることを示唆しています。きっと問題はないでしょう...あなたが問題を理解したら。

そうでなければ:あなたのオプションは何ですか?今後、MongoDBを使用するたびに文字列IDを作成しますか?

1
Dan H

アプリケーションに渡される場合、自動生成されたBSON ObjectIDを一意の識別子として使用することは必ずしも良い考えではないことを付け加えておきます。ユーザーによって操作される可能性があります。 ObjectIDは順次生成されているように見えるため、必要な承認メカニズムを実装できなかった場合、悪意のあるユーザーは自分が持っている値をインクリメントして、アクセスできないはずのリソースにアクセスできます。

そのため、UUIDタイプの識別子を使用すると、あいまいさによるセキュリティの層が提供されます。もちろん、承認(このユーザーが要求されたリソースへのアクセスを許可されているかどうか)は必須ですが、前述のObjectID機能に注意する必要があります。

両方の長所を利用するには、ObjectIDの長さ(12または24文字)に一致するUUIDを生成し、それを使用してObjectIDタイプの独自の_idを作成します。

1
Tony Sepia