【问题标题】:Unique IDs with mongodbmongodb 的唯一 ID
【发布时间】:2010-11-24 01:43:50
【问题描述】:

如果我正在构建一个博客,我可以使用博客标题作为唯一标识符并通过 URL 解析它。但是,如果我想使用数字怎么办。你知道 twitter 如何拥有 www.twitter.com/username/statuses/9834542 吗?有没有人想出一个很好的方法来完成这项工作?使用“_id”是不可能的,因为它太长了。

【问题讨论】:

  • 您可以对 url 进行 md5(或任何)哈希并将其存储在 _id 的位置。

标签: mongodb uniqueidentifier nosql


【解决方案1】:

只要您能保证唯一性,您就不会被限制使用默认的“_id”MongoDB 供应。

因此,如何生成此数字取决于您。如果您想将此数字存储在 MongoDB 中,则可以将其存储在单独的集合中,并为每个所需的新 URL 递增。

增加一个字段是通过使用the $inc verb 来实现的,或者您可能想看看MongoDB 如何atomically update 或增加一个值。

【讨论】:

  • 正如 Alan 所说,您可以提供自己的 id。所以问题是你如何才能独特地生成它。最简单的是如果你有一些序列服务器(即,一个数字然后递增的东西,持有一个锁,所以它会自动发生。这个序列服务器可以为每个序列使用一个 mongo 记录
  • 可以自动递增序列来创建uid吗?
【解决方案2】:

如果您想在 MongoDB 中为自己的字段添加唯一性约束,请使用索引。然后你可以使用任何你想要生成数字的散列算法并测试它的唯一性。 MongoDB 文档中的示例是

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

这将阻止您插入与另一个文档具有相同名字和姓氏的文档。

更多信息请访问documentation

【讨论】:

    【解决方案3】:

    我通过使用数据创建集合“序列”解决了这个问题:

    • 姓名
    • 当前值

    我正在使用Morhpia,所以有DAO。但是你也可以在没有 Morhpia 的情况下做到这一点。 想法是使用 $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 配置(仅一个节点或主/从或副本集),您必须使用正确的 WriteConcern。在具有一个实例的环境中使用 REPLICATION_SAFE 只会导致无限循环。

    【讨论】:

    • 这是什么语言? :) 击中我的眼睛!
    【解决方案4】:

    可以使用findandmodify命令来完成。

    假设我们有一个名为sequences 的特殊集合,并且我们希望有一个帖子编号序列(名为postid),您可以使用类似这样的代码:

    > db.runCommand( { "findandmodify" : "序列", “查询”:{“名称”:“postid”}, “更新”:{$inc:{“id”:1}}, “新”:真});

    此命令将自动返回更新后的 (new) 文档以及状态。如果命令成功完成,value 字段包含返回的文档。

    【讨论】:

    • @BlitzKrieg,根据文档:“findandmodify 将在通过 mongos 调用时表现相同,只要它正在修改的集合是未分片的。如果集合是分片的,那么查询必须包含分片键。”所以,不要对sequences 集合进行分片?
    【解决方案5】:

    从技术上讲,ID 号太大而无法缩短。但是,可以填补一个战术。那是从十六进制传递到字母数字,从而减少了 tulizar 的字符数,并且在 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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      相关资源
      最近更新 更多