Sequelize - Получите все данные с настраиваемым местом - PullRequest
0 голосов
/ 12 июля 2020

Как я могу получить данные с пользовательскими условиями where? В этом вопросе Sequelize - функция для столбца в предложении where , у меня аналогичная проблема, но я считаю, что в этой функции используются MySQL встроенные функции, и она извлекает данные в пределах радиуса.

У меня несколько моделей.

  1. Дом
  2. Адрес
  3. Задача

Каждый house ЕСТЬ МНОГО tasks. и каждый house ИМЕЕТ ОДИН address.

При звонке /getTasks мне нужно получить всю миссию, НО с ограничением:

домашний адрес прямое расстояние должно составлять N километров от широты и долготы запроса.

Я могу просто сделать это, используя findAndCountAll, а затем выполнить вычисление, прежде чем возвращать результат клиенту, НО я уверен, что это будет либо работать медленнее / менее эффективно, либо это нарушит разбиение на страницы.

Вот что у меня есть:

// Get all the available tasks.
// Requirements:
// 1. It accepts the coordinate from the client.
// 2. The client's coordinate must be <= N-Kilometer straight distance.
// 3. Return the tasks WITH PAYMENT and WITHOUT assigned USER.
exports.getTasks = (req, res) => {
  const latitude = parseFloat(req.query.latitude)
  const longitude = parseFloat(req.query.longitude)

  if (!longitude || !latitude) {
    return res.status(200).send({
      errorCode: 101,
      message: "Error! Required parameters are: {longitude} and {latitude}."
    })
  }

  const page = myUtil.parser.tryParseInt(req.query.page, 0)
  const limit = myUtil.parser.tryParseInt(req.query.limit, 10)

  const houseLat = 32.9697
  const houseLong = -96.80322

  console.log("Computing distance of a house (" + latitude + ", " + longitude + ") --- to (" + houseLat + ", " + houseLong + ")")

  point1 = new GeoPoint(latitude, longitude)
  point2 = new GeoPoint(pLat, pLong)

  const distance = point1.distanceTo(point2, true)

  // Begin query...
  db.Task.findAndCountAll({
    where: null, // <----- don't know what to put.
    include: [
      {
        model: db.Order,
        as: "order"
      },
      {
        model: db.House,
        as: "house",
        include: [
          {
            model: db.Address,
            as: "address"
          }
        ]
      }
    ],
    offset: limit * page,
    limit: limit,
    order: [["id", "ASC"]],
  })
    .then(data => {
      res.json(myUtil.response.paging(data, page, limit))
    })
    .catch(err => {
      console.log("Error get all tasks: " + err.message)
      res.status(500).send({
        message: "An error has occured while retrieving data."
      })
    })
}

1 Ответ

1 голос
/ 13 июля 2020

Я выкладываю здесь свое решение. Чтобы дать больше контекста, это приложение для отдыха похоже на поиск горничных / помощников для каждого дома. И эта конкретная c конечная точка (проблема) заключается в том, что клиентское приложение горничных / помощников получает список доступных домов, которые нуждаются в уборке. Условия следующие:

  1. Дом должен находиться на расстоянии не более 10 км от местоположения клиентского приложения.
  2. Задаче не назначен уборщик.

Итак, в этом решении я снова избавился от разбивки на страницы, что довольно сложно. На мой взгляд, вам не нужна разбивка на страницы для этого c дизайна приложения (список предложений, вакансий и т. Д.). А затем просто вычислите расстояние по прямой. Нет необходимости в Google API. Нет необходимости в геопространственных запросах. Возможно, здесь я ошибаюсь, но это все, что я хотел - условие на расстояние <= 10 км по прямой. </p>

// Get all the available tasks.
// We are not using pagination here...
// Makes our lives easier.
// Requirements:
// 1. It accepts the coordinate from the client.
// 2. The client's coordinate must be <= N-Kilometer straight distance.
// 3. Return the tasks WITH ORDER and WITHOUT USER.
exports.getAvailableMissions = (req, res) => {
  const latitude = parseFloat(req.query.latitude)
  const longitude = parseFloat(req.query.longitude)

  if (!longitude || !latitude) {
    return res.status(200).send({
      errorCode: 101,
      message: "Error! Required parameters are: {longitude} and {latitude}."
    })
  }

  // Proceed with searching...
  // user id must equal to null. - means unassigned.
  // order must not be equal to null. - means paid.
  // the order condition is in the promise.
  const condition = { userId: { [op.is]: null } }

  // Begin query...
  db.Mission.findAndCountAll({
    where: condition,
    include: [
      {
        model: db.Order,
        as: "order"
      },
      {
        model: db.Asset,
        as: "asset"
      },
      {
        model: db.House,
        as: "house",
        include: [
          {
            model: db.Address,
            as: "address"
          }
        ]
      }
    ],
    limit: 10,
    order: [["id", "ASC"]],
  })
    .then(data => {
      let newData = JSON.parse(JSON.stringify(data))
      const tasks = newData.rows
      let newRows = []

      for (let task of tasks) {
        const house = task.house
        const address = house.address
        const houseLat = address.latitude
        const houseLong = address.longitude

        const point1 = new GeoPoint(latitude, longitude)
        const point2 = new GeoPoint(houseLat, houseLong)

        const distance = point1.distanceTo(point2, true)
        const distanceInMiles = distance * 0.621371

        console.log("Computing distance (" + latitude + ", " + longitude + ") --- to (" + houseLat + ", " + houseLong + ")")
        console.log("Miles: distance: ", distanceInMiles)

        // 10 miles max straight distance.
        const maxDistance = 10

        if (distanceInMiles <= maxDistance) {
          task.distanceFromMeInMiles = parseFloat(distanceInMiles)
          newRows.push(task)
        }
      }

      // Apply the new rows.
      delete newData.rows
      delete newData.count
      newData.total = newRows.length
      newData.data = newRows

      res.json(newData)
    })
    .catch(err => {
      console.log("Error get all tasks: " + err.message)
      res.status(500).send({
        message: "An error has occured while retrieving data."
      })
    })
}
...