Запись маршрута(координат) пользователя в БД

Для сохранения маршрута пользователя в базе данных, обычно используется набор координат, представляющих его перемещение во времени. Этот набор координат может быть представлен в виде линии или пути, где каждая точка содержит информацию о местоположении (широта и долгота), времени и, возможно, другие дополнительные данные, такие как высота или скорость.

Сохранение в БД PostgreSQL с помощью PostGIS

Одним из распространенных способов хранения маршрутов в базе данных является использование географических типов данных, предоставляемых многими современными базами данных. Например, в PostgreSQL с расширением PostGIS можно использовать тип данных geometry или geography для хранения географических объектов, таких как линии.

Пример создания таблицы для хранения маршрутов в PostgreSQL с использованием PostGIS:

CREATE TABLE user_routes (
    user_id INT,
    route_id SERIAL PRIMARY KEY,
    route_geometry GEOMETRY(LineString, 4326),
    timestamp TIMESTAMP
);

В этом примере:

  • user_id – идентификатор пользователя, чтобы можно было связать маршрут с конкретным пользователем.
  • route_id – уникальный идентификатор маршрута.
  • route_geometry – поле для хранения геометрии маршрута в виде линии (LineString) в системе координат EPSG 4326 (широта/долгота).
  • timestamp – метка времени, указывающая, когда была записана каждая точка маршрута.

Примечание: мы скорее всего будем связывать маршрут с поездкой( trip_id ), а поездка уже с пользователем.(хотя можно привязать и к user тоже)

Когда пользователь записывает свой маршрут, каждая точка маршрута (координаты в определенный момент времени) добавляется в базу данных с указанием соответствующего user_id, создается уникальный route_id, и записывается временная метка.
Позже пользователь может запросить данные из базы данных для визуализации своего маршрута на карте или для анализа перемещения во времени.

Пример конкретной записи маршрута в ячейках этой таблицы

Запись маршрута в ячейках будет выглядеть следующим образом:

INSERT INTO user_routes (user_id, route_geometry, timestamp)
VALUES
  (1, ST_GeomFromText('LINESTRING(30.1234 50.5678, 30.4567 50.9876, 30.7890 50.6543)'), '2022-01-01T12:00:00Z');

В этом примере:

  • user_id: Идентификатор пользователя.
  • route_geometry: Геометрия маршрута, представленная в виде LineString. ST_GeomFromText используется для создания геометрии из текстового представления координат.
  • timestamp: Временная метка, указывающая момент времени, когда была записана точка маршрута.

Таким образом, вы можете использовать функцию ST_GeomFromText, чтобы вставить геометрию маршрута в таблицу user_routes". Помните, что это просто пример, и реальный формат данных будет зависеть от вашего кода вставки данных и формата представления геометрии.

С какой периодичностью(время) координаты записываются в БД

Частота передачи координат на сервер зависит от требований конкретного приложения, его целей и ограничений. В случае отслеживания перемещения пользователя, частота может варьироваться в зависимости от таких факторов, как:

  1. Точность маршрута: Если важна высокая точность отслеживания маршрута, то частота обновления может быть высокой, например, раз в несколько секунд.
  2. Энергопотребление устройства: Чем чаще передаются координаты, тем больше энергии требуется от устройства пользователя (например, смартфона). Поэтому, в контексте мобильных устройств, разработчики могут настраивать частоту обновления, чтобы балансировать точность и энергопотребление.
  3. Необходимость реального времени: Если требуется реальное времени (например, в приложениях для отслеживания передвижения транспорта), частота обновления может быть высокой, чтобы обеспечить актуальные данные.
  4. Требования к пропускной способности сети: Высокая частота обновления может привести к увеличению объема передаваемых данных, что может оказаться важным фактором в приложениях с ограниченной пропускной способностью сети.

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

На примере шеринга самокатов

Для проката шеринговых самокатов, где важна точность и актуальность данных о местоположении, частота обновления может быть настроена на уровне секунд. В большинстве случаев это будет в пределах 1-5 секунд.

Давайте рассмотрим пример:

Если пользователь двигается со скоростью 25 км/час, то за одну секунду он пройдет приблизительно 7 метров (25 км/ч / 3600 сек/ч). Следовательно, если обновлять местоположение каждую секунду, вы сможете получить довольно точное представление о его маршруте.

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

Запись маршрута на стороне клиента. Браузер

Можно использовать локальное хранение данных на стороне клиента, чтобы записывать маршрут и отправлять его в базу данных позже, когда пользователь завершит маршрут. Одним из подходов к этой задаче может быть использование локального хранилища браузера, такого как localStorage" или "IndexedDB.

Пример использования localStorage:

// Начать запись маршрута
function startRecordingRoute() {
    // Инициализировать массив для хранения координат маршрута
    const routeCoordinates = [];

    // Сохранить массив в локальное хранилище
    localStorage.setItem('routeCoordinates', JSON.stringify(routeCoordinates));
}

// Добавить координаты в массив маршрута
function addCoordinateToRoute(latitude, longitude) {
    // Получить текущий массив координат из локального хранилища
    const routeCoordinates = JSON.parse(localStorage.getItem('routeCoordinates')) || [];

    // Добавить новые координаты в массив
    routeCoordinates.push({ latitude, longitude });

    // Обновить массив в локальном хранилище
    localStorage.setItem('routeCoordinates', JSON.stringify(routeCoordinates));
}

// Завершить запись маршрута и сохранить в БД
function finishRecordingAndSaveToDB() {
    // Получить массив координат из локального хранилища
    const routeCoordinates = JSON.parse(localStorage.getItem('routeCoordinates')) || [];

    // Отправить массив координат в вашу базу данных
    // (реализация этой части зависит от вашего стека технологий на сервере)
    // Пример запроса на сервер с использованием fetch:
    fetch('/api/saveRoute', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ route: routeCoordinates }),
    })
    .then(response => response.json())
    .then(data => {
        // Обработать ответ от сервера (если необходимо)
        console.log('Маршрут успешно сохранен в базе данных');
        
        // Очистить локальное хранилище после сохранения в БД
        localStorage.removeItem('routeCoordinates');
    })
    .catch(error => {
        console.error('Произошла ошибка при сохранении маршрута:', error);
    });
}

В этом примере startRecordingRoute и addCoordinateToRoute используются для записи координат в локальное хранилище на стороне клиента. finishRecordingAndSaveToDB отправляет сохраненные координаты на сервер для сохранения в базе данных. После успешного сохранения маршрута данные из локального хранилища удаляются.

Обратите внимание, что использование localStorage имеет ограничения по объему данных, и для более крупных объемов данных может быть разумным использовать IndexedDB.

Запись маршрута на стороне клиента. Мобильное приложение. ReactNative

В мобильном приложении на React Native, вы можете использовать локальное хранение данных, также как и в веб-приложении, но с использованием инструментов, предоставляемых React Native. Вместо localStorage вы можете использовать AsyncStorage для асинхронного хранения данных.

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

import React, { useState } from 'react';
import { View, Button } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';

const RouteRecorder = () => {
  const [routeCoordinates, setRouteCoordinates] = useState([]);

  const startRecordingRoute = async () => {
    // Инициализировать массив для хранения координат маршрута
    await AsyncStorage.setItem('routeCoordinates', JSON.stringify([]));
  };

  const addCoordinateToRoute = async (latitude, longitude) => {
    // Получить текущий массив координат из AsyncStorage
    const storedRoute = await AsyncStorage.getItem('routeCoordinates');
    const routeCoordinates = storedRoute ? JSON.parse(storedRoute) : [];

    // Добавить новые координаты в массив
    routeCoordinates.push({ latitude, longitude });

    // Обновить массив в AsyncStorage
    await AsyncStorage.setItem('routeCoordinates', JSON.stringify(routeCoordinates));

    // Обновить состояние компонента
    setRouteCoordinates(routeCoordinates);
  };

  const finishRecordingAndSaveToDB = async () => {
    // Получить массив координат из AsyncStorage
    const storedRoute = await AsyncStorage.getItem('routeCoordinates');
    const routeCoordinates = storedRoute ? JSON.parse(storedRoute) : [];

    // Отправить массив координат в вашу базу данных
    // (реализация этой части зависит от вашего стека технологий на сервере)
    // Пример запроса на сервер с использованием fetch:
    fetch('https://example.com/api/saveRoute', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ route: routeCoordinates }),
    })
      .then(response => response.json())
      .then(data => {
        // Обработать ответ от сервера (если необходимо)
        console.log('Маршрут успешно сохранен в базе данных');

        // Очистить AsyncStorage после сохранения в БД
        AsyncStorage.removeItem('routeCoordinates');
        setRouteCoordinates([]);
      })
      .catch(error => {
        console.error('Произошла ошибка при сохранении маршрута:', error);
      });
  };

  return (
    <View>
      <Button title="Start Recording" onPress={startRecordingRoute} />
      <Button title="Add Coordinate" onPress={() => addCoordinateToRoute(37.7749, -122.4194)} />
      <Button title="Finish and Save to DB" onPress={finishRecordingAndSaveToDB} />
    </View>
  );
};

export default RouteRecorder;

Этот пример демонстрирует использование AsyncStorage для сохранения и получения данных в React Native. Помните, что AsyncStorage имеет свои ограничения, и его стоит использовать для относительно небольших объемов данных. Если маршруты становятся крупными, вы можете рассмотреть использование других библиотек для управления локальным хранением данных в React Native, таких как react-native-sqlite-storage или realm.