MongoDB не может найти документы с двумя разными полями, включающими одинаковую дату

Я использовал Postgresql для своего проекта, но недавно столкнулся с некоторыми проблемами производительности и решил попробовать MongoDB. Но на этот раз я в другом море проблем, и я тону.

Наиболее важными полями моей таблицы/коллекции являются «Дата начала» и «Дата окончания», потому что с этими датами любые сообщения в моей базе данных могут быть опубликованы на сайте или удалены с сайта.

Вот моя проблема, я надеюсь, что кто-то может мне помочь:

Когда я вставляю сообщение в базу данных, у меня есть два варианта:

1) Этот пост никогда не будет удален с сайта. В этой ситуации я делаю «StartDate» и «EndDate» точно такими же (равными). Это означает, что этот пост никогда не будет удален с сайта, и он может быть опубликован в «Дата начала».

2) Этот пост может быть/будет удален с сайта. Конечно, в данной ситуации «Дата начала» и «Дата окончания» разные, и исходя из этих дат (между этими датами) пост может быть опубликован на сайте.

Почему это важно для меня, потому что теги удаленных сообщений также необходимо удалить со страницы тегов, URL-адреса удаленных сообщений также необходимо удалить из карты сайта и т. д.

В моих таблицах postgresql это не было проблемой и очень простым запросом:

SELECT * FROM posts WHERE 
      SATUS=true AND (
        (enddate = startdate AND startdate <= Now()) 
        OR 
        (enddate <> startdate AND startdate <= Now() AND enddate > Now())
      )

Но в MongoDB я не могу получить правильные результаты из моей коллекции сообщений, даже если я использую эквивалентный синтаксис?

Я несколько дней искал в StackOverflow, и вот самый совершенный синтаксис агрегации, который мне удалось найти. (для MongoShell)

Приведенный ниже запрос возвращает только те поля, которые имеют разные «Дата начала» и «Дата окончания» и в которых в настоящее время публикуются сообщения.

Первая часть И в ИЛИ кажется не работает. Возвращает только результаты второго И.


var tmpDate = new Date();
db.getCollection('Posts').aggregate([
{ $project : {"_id":1,"Status":1,"EndDate":1,"StartDate":1}},
{ $match : 
    { "$and": [ 
        { "Status": true }, 
        { "$or": [
            { "$and": [{ "EndDate": { "$eq": "StartDate" } }, { "StartDate": { "$lte": tmpDate } } ] }, 
            { "$and": [ { "EndDate": { "$ne": "StartDate" } }, { "StartDate": { "$lte": tmpDate } }, { "EndDate": { "$gt": tmpDate } } ] } 
            ] 
        } 
        ] 
    }
}
])

Наконец, я наткнулся на ответ по поводу этой ситуации на StackOverflow, что MongoDB не может найти одинаковые даты или сравнить их, как другие БД?

Как я могу выполнить эту фильтрацию? Или я должен остаться с Postgresql.

PS: я вставляю тестовые документы из консольного приложения С# и вставляю даты как даты ISO:

DateTime tmpNow = DateTime.UtcNow;
tmpNow = Convert.ToDateTime(tmpNow.ToString("yyyy-MM-ddTHH:mm:00")).ToUniversalTime();

Я добавляю образец документа по запросу:

{
    "_id" : NumberLong(1),
    "Status" : true,
    "Cat" : [ 
        4
    ],
    "Type" : 1,
    "Title" : {
        "Normal" : "Class aptent taciti sociosqu ad litora torquent per conubia",
        "Spot" : null,
        "Small" : null,
        "Seo" : null
    },
    "Summary" : "Nam finibus nulla quis.",
    "Article" : "<p>Maecenas malesuada augue nec</p>",
    "Picture" : {
        "Path" : "/Content/Images/detay9.jpg",
        "Anchor" : "top",
        "Rank" : 0,
        "Desc" : null,
        "Width" : 843,
        "Height" : 1022
    },
    "Vertical" : null,
    "Source" : "StackOverflow",
    "Editor" : "An Editor",
    "Related" : null,
    "Tags" : [ 
        "Causae", 
        "Nusquam", 
        "Percipitur", 
        "Rihanna", 
        "Saglik"
    ],
    "StartDate" : ISODate("2019-05-05T13:44:00.000Z"),
    "EndDate" : ISODate("2019-05-05T13:44:00.000Z"),
    "UpdateDate" : ISODate("2019-05-05T13:44:00.000Z"),
    "Rank" : 100,
    "ReadCount" : 1064,
    "Gallery" : null,
    "List" : null,
    "Shared" : false,
    "Video" : null
}

person Cem    schedule 03.08.2019    source источник
comment
Пожалуйста, добавьте пример данных и опишите, что вы подразумеваете под «Но в MongoDB я не могу получить результаты из моей коллекции сообщений». Он пуст? Это неверные данные? Выдает ошибку?   -  person str    schedule 04.08.2019
comment
Спасибо, что упомянули результаты. После второй проверки я выяснил, что работает и возвращает результат только второй оператор AND. Первое И не работает. Это означает, что сообщения с одинаковыми StartDate и EndDate не возвращаются.   -  person Cem    schedule 04.08.2019
comment
Вы хотите вернуть только те данные, которые имеют одинаковые StartDate и EndDate . Это твоя проблема?   -  person MilanRegmi    schedule 04.08.2019
comment
Нет, я хочу два типа сообщений, поэтому у меня есть два И в моем ИЛИ: 1) StartDate и EndDate равны и меньше, чем now(). и 2) StartDate и EndDate разные, StartDate меньше, чем now(), EndDate больше, чем сейчас.   -  person Cem    schedule 04.08.2019


Ответы (1)


Пожалуйста, попробуйте это, я надеюсь, что это сработает для вас:

db.getCollection('Posts').aggregate([
    {
        $match:
        {
            "Status": true, "StartDate": { "$lte": tmpDate },
            $expr: { $or: [{ $eq: ['$StartDate', '$EndDate'] }, { $gt: ['$EndDate', tmpDate] }] }
        }
    },
    { $project: {"Status": 1, "EndDate": 1, "StartDate": 1 } }
])

Примечание.

1) В конечном результате, если вы хотите _id, то в $project вам не нужно делать "_id":1, оно будет существовать по умолчанию, вы должны указать "_id":0, если вам не нужно это поле.

2) Возвращаясь к вашему заявлению: Finally, I came across to answer about this situation at StackOverflow that MongoDB can not find equal dates or compare them like other DBs?. Исходя из моего опыта, я бы сказал, что мы можем сделать, если оба поля имеют один и тот же тип, иначе вам нужно преобразовать одно в другое, также если вы сравнение двух полей в документе mongoDB с использованием $expr поможет. Было бы неплохо использовать $match как можно раньше, чтобы вы могли фильтровать документы, а затем выполнять необходимые операции.

person whoami - fakeFaceTrueSoul    schedule 04.08.2019
comment
Очень умный. Я вижу, что вы сначала сократили мой исходный запрос sql и переместили условие startdate ‹= now() на один уровень выше, потому что оно находится в обоих разделах AND. И затем вы также удалили дату начала ‹› дату окончания, потому что мы уже проверяем их равенство в первой части ИЛИ, это означает, что если они не совпадают, значит, они не равны, и нам не нужно проверять снова. Наконец, вы проверяете дату окончания › now(). И да, ваш код работает, я благодарен, большое спасибо. Я думаю, что $exprв вашем коде происходит волшебство. - person Cem; 04.08.2019