Как найти все документы MongoDB, вставленные между двумя LocalDateTime - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь разработать приложение, которое извлекает все документы, вставленные за определенный период.

Это мой пример кода:

MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("eam");
MongoCollection<Document> collection = database.getCollection("coll");

List<Document> docsList = new ArrayList<>();

LocalDateTime initDate = LocalDateTime.now();
LocalDateTime endDate = initDate.plusSeconds(5);
int i = 0;
while (LocalDateTime.now().isBefore(endDate)) {
    Document doc = new Document("id", i)
            .append("name objy", "Obj " + i)
            .append("timeStamp", LocalDateTime.now());
    docsList.add(doc);
    i++;
}

collection.insertMany(docsList);

MongoCursor<Document> cursor = collection.find(new Document("timestamp", new Document("$gte", endDate.minusSeconds(3)).append("$lte", endDate.minusSeconds(2)))).iterator();
try {
    while (cursor.hasNext()) {
        System.out.println(cursor.next().toJson());
    }
} finally {
    cursor.close();
}

Как @Valijo, я изменил свойкод для фильтрации по gte и lte, но теперь ничего не возвращается!Почему?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

$in выбирает точные значения в качестве заданного массива.

Таким образом, вам необходимо сохранить точное значение timestamp (с точностью до 1 мс)

Проблема здесь:

LocalDateTime initDate = LocalDateTime.now();
LocalDateTime endDate = initDate.plusSeconds(5);
int i = 0;
while (LocalDateTime.now().isBefore(endDate)) { 
    Document doc = new Document("id", i)
            .append("name objy", "Obj " + i)
            .append("timeStamp", LocalDateTime.now()); //<-- The timestamp ms may differ from initDate ms
    docsList.add(doc);
    i++;
}

Решение 1: При вставке документов используйте:

initDate.plusSeconds(i)

И тогда ваш запрос вернет то, что вы ожидаете

Решение2: (Вы можете перевести на свой язык программирования)

Сохранить timeStamp ссылки и затем искать их

var date1 = new Date(1537457334015); //Thursday, 20 September 2018 15:28:54.015
var date2 = new Date(1537457335014); //Thursday, 20 September 2018 15:28:55.014

var date3 = new Date(1537457336015); //Thursday, 20 September 2018 15:28:56.015 1 sec 1 ms
var date4 = new Date(1537457336025); //Thursday, 20 September 2018 15:28:56.025 2 sec 11 ms 

var date2Plus1Sec = new Date( date2.getTime() + 1000 );

//db.coll.remove({})

db.coll.insert([
    {
        "timeStamp" : date1
    },
    {
        "timeStamp" : date2
    },
    {
        "timeStamp" : date3
    },
    {
        "timeStamp" : date4
    }
])

db.coll.find({"timeStamp" :{$in: [date1, date2, date2Plus1Sec ]} } ).pretty();

Результат:

/* 1 */
{
    "_id" : ObjectId("5ba3bea3ba135b198e17ec2d"),
    "timeStamp" : ISODate("2018-09-20T15:28:54.015Z")
}

/* 2 */
{
    "_id" : ObjectId("5ba3bea3ba135b198e17ec2e"),
    "timeStamp" : ISODate("2018-09-20T15:28:55.014Z")
}

ИтакThursday, 20 September 2018 15:28:56.014 не существует в базе данных

Решение 3: Не используйте точное совпадение значений и используйте операторы $gte и $lte для поиска timeStamp range

0 голосов
/ 20 сентября 2018

Посмотрите на https://docs.mongodb.com/manual/reference/method/Date/, если вы не хотите работать с отметками времени

$ в проверках, если отметка времени равна одному из значений внутри $ in: https://docs.mongodb.com/manual/reference/operator/query/in/

Но вам нужен промежуток, этот код должен работать для вас:

 db.yourcollection.find({$gte: {'timestamp': min}, $lte: {'timestamp': max}})

пожалуйста, обратите внимание: приведенный выше код предназначен для оболочки mongo, но вы должны иметь возможность "перевести" его на свойнеобходимый синтаксис

РЕДАКТИРОВАТЬ: также помните, что время Mongodbs всегда UTC

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...