【Mongo】MongoDb的_id生成规则

MongoDB的文档必须有一个_id键。

目的是为了确认在集合里的每个文档都能被唯一标识。

ObjectId 是 _id 的默认类型。

ObjectId 采用12字节的存储空间,每个字节两位16进制数字,是一个24位的字符串。

12位生成规则:

[0,1,2,3] [4,5,6] [7,8] [9,10,11]

时间戳 |机器码 |PID |计数器

  前四字节是时间戳,可以提供秒级别的唯一性。
  接下来三字节是所在主机的唯一标识符,通常是机器主机名的散列值。
  接下来两字节是产生ObjectId的PID,确保同一台机器上并发产生的ObjectId是唯一的。
  
最后三字节是自增计数器,确保相同进程同一秒钟产生的ObjectId是唯一的。
前九字节保证了同一秒钟不同机器的不同进程产生的ObjectId时唯一的。 

由此可得,在对数据库数据进行排序/查询时,可以直接根据_id来进行排序/查询(因为生成规则前四字节是时间戳,有秒级的唯一性)

 

代码示例:

//举例说明:例如要查询 30天之前的一整天的mongo记录
    public static void main(String[] args) throws ParseException {
        LocalDateTime ltDate = LocalDateTime.now().plusDays(-30);
        LocalDateTime gtDate = LocalDateTime.now().plusDays(-29);
        System.out.println("ltDate:" + ltDate);
        System.out.println("gtDate:" + gtDate);
        String ltDateTimeStampHex =  mongoIdHandler(getDate(ltDate));
        System.out.println("$lt:" + ltDateTimeStampHex);
        String gtDateTimeStampHex =  mongoIdHandler(getDate(gtDate));
        System.out.println("$gt:" + gtDateTimeStampHex);



        BasicDBObject cond = new BasicDBObject();
        //_id的查询条件是时间
        BasicDBObject time = new BasicDBObject();
        cond.put("_id", time);
        time.put("$lt", new ObjectId(ltDateTimeStampHex));
        time.put("$gt", new ObjectId(gtDateTimeStampHex));

    }

    private static Date getDate(LocalDateTime localDateTime){
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        java.util.Date date = Date.from(instant);
        return  date;
    }


    /**
     * 根据时间获取秒,根据秒转化16进制,再补16个0 补齐24位
     *
     * @param date 日期
     * @return {@link String}
     */
    private static String mongoIdHandler(Date date) {
        //获取秒
        long secondTimstamp = date.getTime() / 1000;
        //将秒转换为16进制
        String strHex = Long.toHexString(secondTimstamp);
        //将16进制后边补充16个0
        String _id = strHex + "0000000000000000";
        return _id;
    }

 

 

 

posted @ 2023-07-26 15:29  Angel挤一挤  阅读(807)  评论(0编辑  收藏  举报