Sequelize - Get all data with custom where

三世轮回 提交于 2020-07-23 06:31:10

问题


How can I get data with custom where conditions? In this question Sequelize - function on column in a where clause, I have a similar problem, but this one I believe uses MySQL built-in functions and it fetches data within a radius.


I have several models.

  1. House
  2. Address
  3. Task

Each house HAS MANY tasks. and each house HAS ONE address.

When calling /getTasks, I need to get all the mission BUT with a constraint of:

house address straight distance must be N-Kilometers away from request's lat-long.

I can just do this easily using findAndCountAll and then do the computation before returning the result to the client, BUT I'm sure this will either run slower/less efficient OR this will break the pagination.


Here's what I have so far:

// 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:


I'm posting here my solution. To give more context, this rest app is like a finder for maids/helpers for each house. And this specific endpoint (the problem) is for the maids/helpers client app to get the list of available houses that are in need of cleaning. The conditions are:

  1. House must be within 10KM straight distance from client app's location.
  2. The Task has no assigned cleaner.

So in this solution, again, I get rid of the pagination - which kinda complicated things. In my opinion, you don't need a pagination for this specific kind of app design (listing of offers, jobs, and whatnot). And then just literally compute the straight distance. No need for Google APIs. No need for Geospatial queries. I might be wrong here, but that's all I wanted - a <= 10KM straight distance condition.

// 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."
      })
    })
}


来源:https://stackoverflow.com/questions/62860863/sequelize-get-all-data-with-custom-where

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!