19

ブログを作成している場合は、ブログのタイトルを一意の識別子として使用し、URLを解析することができます。ただし、数字を使用したい場合はどうなりますか。Twitterがwww.twitter.com/username/statuses/9834542をどのように持っているか知っていますか?誰かがこれを機能させる良い方法を見つけましたか?「_id」の使用は長すぎるため、問題外です。

4

5 に答える 5

24

一意性を保証できる限り、MongoDB が提供するデフォルトの "_id" を使用する必要はありません。

したがって、この数値をどのように生成するかはあなた次第です。この番号を MongoDB 内に保存したい場合は、それを別のコレクションに保存し、必要な新しい URL ごとに増分することができます。

フィールドのインクリメントは$inc動詞を使用して実現されます。または、MongoDB が値をアトミックに更新またはインクリメントする方法を確認することもできます。

于 2009-09-02T17:13:16.780 に答える
17

これは、 findandmodifyコマンドを使用して実行できます。

sequencesという名前の特別なコレクションがあり、投稿番号 ( という名前) のシーケンスが必要だと考えてみましょう。次のpostidようなコードを使用できます。

> db.runCommand( { "findandmodify" : "シーケンス",
                   "クエリ" : { "名前" : "postid"},
                   "更新": { $inc: { "id": 1 }},
                   「新しい」: 真 } );

このコマンドは、更新された ( new) ドキュメントとステータスをアトミックに返します。コマンドが正常に完了した場合、valueフィールドには返されたドキュメントが含まれます。

于 2010-10-12T21:52:19.430 に答える
7

MongoDB の独自のフィールドに一意性制約を追加する場合は、インデックスを使用します。次に、任意のハッシュ アルゴリズムを使用して数値を生成し、一意性をテストできます。MongoDB ドキュメントの例は次のとおりです。

db.things.ensureIndex({firstname: 1, lastname: 1}, {unique: true});

これにより、別のドキュメントと同じ名と姓を持つドキュメントを挿入できなくなります。

詳細については、ドキュメントを参照してください。

于 2010-05-27T18:01:39.320 に答える
4

データを使用してコレクション「シーケンス」を作成することで、この問題を解決しました。

  • 名前
  • 現在値

私はMorhpiaを使用しているので、DAO を使用します。ただし、モーピアがなくてもできます。アイデアは、 $atomic (おそらく 1 つのインスタンスのみを更新するため省略できる) と$inc修飾子演算子を使用することです。

順序

@Entity(value = "sys_sequence", noClassnameStored = true)
public class SequenceM {

    /**
     * Names of entity
     */
    public static enum Entity {
        USER,
        CAPABILITY_HISTORY;

        public String getEntityName() {
            return this.name().toLowerCase();
        }
    }

    @Id
    private ObjectId uid;

    @Property
    @Indexed(unique = true)
    private String name;

    @Property
    private Long value;

 //..getters/setters/etc
 }

SequenceDAO のメソッド:

@NotNull
public Long nextValue(final @NotNull SequenceM.Entity entity) {
    final DB db = this.ds.getDB();
    final WriteConcern writeConcern = getWriteConcern();

    //optimization for JVM instance
    synchronized(entity) {
        do {
            SequenceM sequence = findOne("name", entity.getEntityName());

            final DBObject q = BasicDBObjectBuilder.start().add("name", entity.getEntityName()).add("value", sequence.getValue()).add("$atomic", 1).get();
            final DBObject o = BasicDBObjectBuilder.start().add("$inc", BasicDBObjectBuilder.start().add("value", 1).get()).get();

            WriteResult writeResult = db.getCollection("sys_sequence").update(q, o, false, true, writeConcern);

            if(writeResult.getN() == 1) {
                return sequence.getValue() + 1;
            }
        } while(true);
    }
}

/**
 * Determining writing concern basing on configuration
 */
private WriteConcern getWriteConcern() {
    return isOneNodeOnly ? WriteConcern.SAFE : REPLICATION_SAFE;
}

MongoDB の構成 (1 つのノードのみ、またはマスター/スレーブまたはレプリカ セット) に応じて、正しい WriteConcern を使用する必要があります。1 つのインスタンスを持つ 1 つの環境で REPLICATION_SAFE を使用すると、無限ループが発生するだけです。

于 2010-09-25T11:31:02.990 に答える
1

技術的には、ID番号が大きすぎて短縮できません。ただし、戦術は満たすことができます。これは16進数から英数字に移行するため、文字数が減少してURLになり、URLでより美しく見えます。私は本当にとてもよく仕えました...ここにあります

function encode(hex) {
    return new Buffer(hex, 'hex').toString('base64').replace('+', '-').replace('/', '_');
};

function decode(NoHex) {
    return new Buffer( NoHex.replace('-','+').replace('_','/'), 'base64').toString('hex');
};

IdString= MyDoc._id.toString(); 
Idencode = encode( IdString ) // 16 Caracters a-Z and 0-9 
console.log( IdEncode ); //You see That 'aqswedasdfdsadsf'
IdDecode = decode( IdEncode );
IdDecode === IdString // Is true!!!

もちろん、この手法では同じID、mongoを使用します。

于 2013-01-14T03:46:30.577 に答える