web-dev-qa-db-ja.com

一意のユーザーIDのシーケンスを保存するMongoDBの自動インクリメント

私は分析システムを作成していますが、API呼び出しは一意のユーザーIDを提供しますが、順序が正しくなく、まばらです。

Bitarray/bitsetの分析データポイントをマークするには、各一意のユーザーIDに自動インクリメントIDを与える必要があります。したがって、最初のユーザーはビット配列の最初のビットに対応し、2番目のユーザーはビット配列の2番目のビットになります。

それでは、MongoDBでインクリメンタルユニークユーザーIDを生成するための確実で高速な方法はありますか?

20
est

できますが、できません https://web.archive.org/web/20151009224806/http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/

Mongoの各オブジェクトにはすでにIDがあり、挿入順にソートできます。ユーザーオブジェクトのコレクションを取得し、それを反復処理し、これを増分IDとして使用することの何が問題になっていますか? Erは完全に一種のmap-reduceジョブに行きます

12

選択した答えにあるように、findAndModifyを使用してシーケンシャルIDを生成できます。

しかし、私はあなたがそうすべきではないという意見に強く反対します。それはすべて、ビジネスニーズによって異なります。 12バイトのIDを持つことは、非常にリソースを消費し、将来的に大きなスケーラビリティの問題を引き起こす可能性があります。

詳細な答えがあります here .

21
expert

最初にcountersコレクションを作成します。これは、すべてのシーケンスフィールドの最後のシーケンス値を追跡します。

        db.createCollection("counters")

次のコードを使用して、このシーケンスドキュメントをカウンタコレクションに挿入します-

    db.counters.insert({_id:"tid",sequence_value:0})

JavaScript関数の作成:

    function getNextSequenceValue(sequenceName){
        var sequenceDocument = db.counters.findAndModify({
        query:{_id: sequenceName },
        update: {$inc:{sequence_value:1}},
        new:true
          });
      return sequenceDocument.sequence_value;
      }

2つのドキュメントを挿入します。

            db.products.insert({
           "_id":getNextSequenceValue("tid"),
           "product":"Samsung",
           "category":"mobiles"
             })


           db.products.insert({
            "_id":getNextSequenceValue("tid"),
            "product":"Samsung S3",
            "category":"mobiles"
              })

挿入されたドキュメントを取得:

            db.prodcuts.find()

[〜#〜] output [〜#〜]

{「_id」:1、「product」:「Samsung」、「category」:「mobiles」}

{"_id":2、 "product": "Samsung S3"、 "category": "mobiles"}

13

これは古い質問ですが、後世のために答えを投稿します...

構築しているシステムと特定のビジネスルールによって異なります。

MongoDb、C#(バックエンドAPI)、およびAngular(フロントエンドWebアプリ)で中規模から大規模のCRMを構築していますが、特定のエンティティを選択するためのAngularルーティングで使用するにはObjectIdが非常にひどいことがわかりました。 API Controllerルーティングと同じです。

上記の提案は、私のプロジェクトにとって完璧に機能しました。

db.contacts.insert({
 "id":db.contacts.find().Count()+1,
 "name":"John Doe",
 "emails":[
    "[email protected]",
    "[email protected]"
 ],
 "phone":"555111322",
 "status":"Active"
});

それが私の場合に最適な理由は、すべての場合ではありませんが、上記のコメントが示すように、コレクションから3つのレコードを削除すると、衝突が発生するためです。

私のビジネスルールでは、社内のSLAにより、作成中のアプリケーションの潜在的な寿命よりも長い間、通信データまたはクライアントレコードを削除することは許可されていません。したがって、単にレコードに列挙「ステータス」をマークします。 「アクティブ」または「削除済み」のいずれかです。 UIから何かを削除できます。「連絡先は削除されました」と表示されますが、アプリケーションが行うことは連絡先のステータスを「削除済み」に変更することだけです。アプリが連絡先リストのリポジトリを呼び出すと、フィルタリングしますデータをクライアントアプリにプッシュする前に、削除されたレコードを削除します。

したがって、db.collection.find()。count()+ 1は私にとって完璧なソリューションです...

すべてのユーザーに有効ではありませんが、データを削除しない場合は正常に機能します。

7
Alex Nicholas

最初のレコードを追加する必要があります

"_id" = 1    in your db

$database = "demo";
$collections ="democollaction";
echo getnextid($database,$collections);

function getnextid($database,$collections){

     $m = new MongoClient();
    $db = $m->selectDB($database);
    $cursor = $collection->find()->sort(array("_id" => -1))->limit(1);
    $array = iterator_to_array($cursor);

    foreach($array as $value){



        return $value["_id"] + 1;

    }
 }
0
Darshan Vithani