k12th
@k12th
console.log(`You're pulling my leg, right?`);

Как в MongoDB найти почти равные углы?

В MongoDB лежат объекты, у которых одно из свойств — угол в градусах, целые числа от 0 до 359 (если совсем честно, то это азимут).

Мне нужно находить объекты, угол у которых отличается от заданного не более чем на 22.5 градуса. Первая версия такова:

var directionTolerance = 45 / 2;

var query = {
    $or: [
        {
            direction: {
                $gte: newDirection - directionTolerance, // newDirection -- искомый угол
                $lte: newDirection + directionTolerance
            }
        },
        {
            direction: {
                $gte: 360 + newDirection - directionTolerance,
                $lte: 360 + newDirection + directionTolerance
            }
        },
        {
            direction: {
                $gte: 360 - newDirection - directionTolerance,
                $lte: 360 - newDirection + directionTolerance
            }
        }
    ]
};


К сожалению, этот запрос иногда дает false positive: например, может вернуть объект с углом 0 при угле в запросе 173.
Как сделать правильно?
  • Вопрос задан
  • 360 просмотров
Решения вопроса 1
@lega
Операция "$or" медленная, можно её выкинуть и сделать так - хранить координату в нескольких разрезах:
{
direction: 350,
direction_index: [-10, 350]
}
и искать уже по индексу:
.find({direction_index: { $lte: -22, $gte: 22}})
в итоге вам нужно что-бы фильтр укладывался в -360..360
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
miraage
@miraage
Старый прогер
Понятия не имею, а там синусы/косинусы есть? Может тригонометрия поможет?)
Ответ написан
zoonman
@zoonman
⋆⋆⋆⋆⋆
Обычно в NoSQL применяют предварительную квантификацию данных.
Т.е. у вас есть погрешность π/8, а круг 2π, то ваш квантификатор будет массивом от 0 до 16. У каждого объекта будет свойство quantified_direction, хранящее нужное значени и выборка будет примитивной.
Более простое объяснение - разбейте круг на 16 секторов и записывайте номер для каждого сектора прямо в объект. При поиске просто используйте этот номер. Также вы можете увеличить значение до 32 и делать поиск по двум секторам одновремено. После построения индекса для quantified_direction вы будет получать результаты за доли секунды на огромных базах.
А в целом у вас ошибка в подготовке условия. Нарисуйте круг, вырежьте сектор из бумаги и поработайте с граничными условиями. Задача на самом деле простая.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы