MongoDB ObjectId'yi tarihe göre sorgulayabilir miyim?


Yanıtlar:


224

Zaman Damgalarını ObjectIds içine atmak , ObjectId içine gömülü tarihleri ​​temel alan sorguları ayrıntılı olarak kapsar.

Kısaca JavaScript kodunda:

/* This function returns an ObjectId embedded with a given datetime */
/* Accepts both Date object and string input */

function objectIdWithTimestamp(timestamp) {
    /* Convert string date to Date object (otherwise assume timestamp is a date) */
    if (typeof(timestamp) == 'string') {
        timestamp = new Date(timestamp);
    }

    /* Convert date object to hex seconds since Unix epoch */
    var hexSeconds = Math.floor(timestamp/1000).toString(16);

    /* Create an ObjectId with that hex timestamp */
    var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");

    return constructedObjectId
}


/* Find all documents created after midnight on May 25th, 1980 */
db.mycollection.find({ _id: { $gt: objectIdWithTimestamp('1980/05/25') } });

29
Çok kullanışlı .. FYI, kabuk başladığında ~/.mongorc.jskullanılabilir olması için bu işlevi dosyanıza kaydedebilirsiniz mongo.
Stennie

1
ReferenceError: ObjectId tanımlı değil. Bunu nasıl düzeltirim?
peter

3
Mongodbnative ile nodejs kullanıyorum. Var ObjectId = requir ('mongodb') dahil ederek "tanımlanmadı hatası" düzeltildi.
peter

1
Değişiklik: Mongoskin kullanıyorsanız benim gibi ObjectId(hexSeconds + "0000000000000000");hiçdb.ObjectID.createFromHexString(hexSeconds + "0000000000000000");
Anders Östman

2
Veya Mongoose'da, aşağıdakilerle değiştirin ObjectId(): require('mongoose').Types.ObjectId()- require('mongoose')başlangıç ​​/ yapılandırılmış Mongoose örneğiniz nerede .
toblerpwn

35

İçinde pymongoşu şekilde yapılabilir:

import datetime
from bson.objectid import ObjectId
mins = 15
gen_time = datetime.datetime.today() - datetime.timedelta(mins=mins) 
dummy_id = ObjectId.from_datetime(gen_time)
result = list(db.coll.find({"_id": {"$gte": dummy_id}}))

Datetime.datetime.utcnow () veya datetime.datetime.today () kullanmanın aynı sonucu döndüreceğini unutmayın. Tarih saat sizin için halledilir.
radtek

Alternatif olarak, pymongobağımlılık kullanmadan : epoch_time_hex = format(int(time.time()), 'x') (sorgunuz için sıfır eklemeyi unutmayın) Zaman paketi kullanıldı ( import time).
VasiliNovikov

OP'nin javascript istediğini fark ettim, ama bu gerçekten kodumu basitleştirmeme yardımcı oldu. Teşekkürler.
Fred S

34

Node.js'de mongodb sürücüleri tarafından sağlanan dahili işlevi kullanmak, herhangi bir zaman damgasına göre sorgu yapmanızı sağlar:

var timestamp = Date.now();
var objectId = ObjectID.createFromTime(timestamp / 1000);

Alternatif olarak, geçerli saatten önce kayıtları aramak için şunları yapabilirsiniz:

var objectId = new ObjectID(); // or ObjectId in the mongo shell

Kaynak: http://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html


3
Bir javascript env bir zaman damgası bir ObjectId oluşturmak için en iyi / en kolay yoludur. Op ne ister ...
Anders Östman

14

ObjectId öğesinin ilk 4 baytı bir zaman damgasını temsil ettiğinden , koleksiyonunuzu kronolojik olarak sorgulamak için kimliğe göre sıralayın:

# oldest first; use pymongo.DESCENDING for most recent first
items = db.your_collection.find().sort("_id", pymongo.ASCENDING)

Belgeleri aldıktan sonra, ObjectId'ın oluşturma süresini aşağıdaki gibi alabilirsiniz :

id = some_object_id
generation_time = id.generation_time

1
Aslında ObjectId katıştırılmış zaman kullanarak belirli bir süre önce oluşturulan nesnelerin sayısı almak gibi şeyler yapmak için izin verecek bir şey umuyordum, ama bu doğrudan erişilebilir olmaz gibi görünüyor. Teşekkürler.
Zach

1
Bunu yapabilirsin, Leftium'un cevabına bak.
atp

14

Komut nasıl bulunur (bu tarih [2015-1-12] bu tarihe [2015-1-15]):

db.collection.find ({_ id: {$ gt: ObjectId (Math.floor ((yeni Tarih ('2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt: ObjectId (Math.floor ((yeni Tarih ('2015/1/15')) / 1000) .toString (16) + "0000000000000000")}}.) Pretty ()

Komutu sayın (bu tarih [2015-1-12] bu Tarihe [2015-1-15]):

db.collection.count ({_ id: {$ gt: ObjectId (Math.floor ((yeni Tarih ('2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt: ObjectId (Math.floor ((yeni Tarih ('2015/1/15')) / 1000). ToString (16) + "0000000000000000")}})

Komutu Kaldır (bu tarih [2015-1-12] bu Tarihe [2015-1-15]):

db.collection.remove ({_ id: {$ gt: ObjectId (Math.floor ((yeni Tarih ('2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt: ObjectId (Math.floor ((yeni Tarih ('2015/1/15')) / 1000). ToString (16) + "0000000000000000")}})


10

$convert4.0 sürümünden başlayarak tarihi ObjectId'den ayıklamak için işlevi kullanabilirsiniz .

Gibi bir şey

$convert: { input: "$_id", to: "date" } 

Tarih için başlangıç ​​ve bitiş saatlerini karşılaştırarak tarihte sorgulama yapabilirsiniz.

db.collectionname.find({
  "$expr":{
    "$and":[
      {"$gte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T00:00:00.000Z")]},
      {"$lte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T11:59:59.999Z")]}
    ]
  }
})

VEYA

$toDateAynı şeyi elde etmek için steno kullanabilirsiniz .

db.collectionname.find({
  "$expr":{
    "$and":[
      {"$gte":[{"$toDate":"$_id"}, ISODate("2018-07-03T00:00:00.000Z")]},
      {"$lte":[{"$toDate":"$_id"},ISODate("2018-07-03T11:59:59.999Z")]}
    ]
  }
})

Sadece $ convert OR $ toDate kullanarak sormak istedim, Mongo önce dönüştürmek ve daha sonra doc aralığında olup olmadığını karşılaştırmak zorunda kalacak, ama kabul edilen cevap yaklaşımı kullanır ve daha sonra tarihi bir ObjectId dönüştürmek gerekir müşteri tarafında ve sadece bir kez, Yani çözümün bundan daha verimli olacağını düşünmüyor musunuz? Bu iki operatörün de var olduğunu söylediğin için teşekkürler :)
Sudhanshu Gaur

7

Moğol toplama son 60 gün eski belgeleri almak için ben aşağıda kabuk sorguda kullanılır.

db.collection.find({_id: {$lt:new ObjectId( Math.floor(new Date(new Date()-1000*60*60*24*60).getTime()/1000).toString(16) + "0000000000000000" )}})

1
$ Lt yerine $ gt kullanın. Aksi takdirde, daha önce (bugün-60 gün) eklenen belgeleri bulur.
yoooshi

1
İlk 4 bayt @Vivek NesneKimliği Unix Zaman (1970/01/01 00:00:00 UTC'den) itibaren saniye sayısını temsil eder, ve bu gibi ($ gt) daha büyük ile kullanmak ve daha az (daha $ lt) Belirli bir pencerede oluşturulan nesneleri bulmak için.
John

5

Bir aralık sorgusu yapmak istiyorsanız, bu yayında olduğu gibi yapabilirsiniz . Örneğin, belirli bir gün için sorgulama (örn. 4 Nisan 2015):

> var objIdMin = ObjectId(Math.floor((new Date('2015/4/4'))/1000).toString(16) + "0000000000000000")
> var objIdMax = ObjectId(Math.floor((new Date('2015/4/5'))/1000).toString(16) + "0000000000000000")
> db.collection.find({_id:{$gt: objIdMin, $lt: objIdMax}}).pretty()


2

MongoObjectID kullanarak, aşağıda verilen sonuçları da bulmalısınız

db.mycollection.find({ _id: { $gt: ObjectId("5217a543dd99a6d9e0f74702").getTimestamp().getTime()}});

3
sorgu ifadeniz, başlangıçta her zaman böyle olmayan ObjectId değerini bildiğini varsayar.
Dwight Spencer

0

Raylarda şunu mongoidkullanarak sorgulayabilirsiniz:

  time = Time.utc(2010, 1, 1)
  time_id = ObjectId.from_time(time)
  collection.find({'_id' => {'$lt' => time_id}})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.