Find points near LineString in mongodb sorted by distance

后端 未结 2 525
难免孤独
难免孤独 2021-02-04 10:28

I have an array of points representing a street (black line) and points, representing a places on map (red points). I want to find all the points near the specified street, sort

相关标签:
2条回答
  • 2021-02-04 10:37

    As you mentioned, Mongo currently doesn't support anything other than Point. Have you come across the concept of a route boxer? 1 It was very popular a few years back on Google Maps. Given the line that you've drawn, find stops that are within dist(x). It was done by creating a series of bounding boxes around each point in the line, and searching for points that fall within the bucket.

    I stumbled upon your question after I just realised that Mongo only works with points, which is reasonable I assume.

    I already have a few options of how to do it (they expand on what @mnemosyn says in the comment). With the dataset that I'm working on, it's all on the client-side, so I could use the routeboxer, but I would like to implement it server-side for performance reasons. Here are my suggestions:

    1. break the LineString down into its individual coordinate sets, and query for $near using each of those, combine results and extract an unique set. There are algorithms out there for simplifying a complex line, by reducing the number of points, but a simple one is easy to write.

    2. do the same as above, but as a stored procedure/function. I haven't played around with Mongo's stored functions, and I don't know how well they work with drivers, but this could be faster than the first option above as you won't have to do roundtrips, and depending on the machine that your instance(s) of Mongo is(are) hosted, calculations could be faster by microseconds.

    3. Implement the routeboxer approach server-side (has been done in PHP), and then use either of the above 2 to find stops that are $within the resulting bounding boxes. Heck since the routeboxer method returns rectangles, it would be possible to merge all these rectangles into one polygon covering your route, and just do a $within on that. (What @mnemosyn suggested).

    4. EDIT: I thought of this but forgot about it, but it might be possible to achieve some of the above using the aggregation framework.

    It's something that I'm going to be working on soon (hopefully), I'll open-source my result(s) based on which I end up going with.

    EDIT: I must mention though that 1 and 2 have the flaw that if you have 2 points in a line that are say 2km apart, and you want points that are within 1.8km of your line, you'll obviously miss all the points between that part of your line. The solution is to inject points onto your line when simplifying it (I know, beats the objective of reducing points when adding new ones back in).

    The flaw with 3 then is that it won't always be accurate as some points within your polygon are likely to have a distance greater than your limit, though the difference wouldn't be a significant percentage of your limit.

    [1] google maps utils routeboxer

    0 讨论(0)
  • 2021-02-04 10:55

    As you said Mongo's $near only works on points not lines as the centre point however if you flip your premise from find points near the line to find the line near the point then you can use your points as the centre and line as the target

    this is the difference between

    foreach line find points near it
    

    and

    foreach point find line near it
    

    if you have a large number of points to check you can combine this with nevi_me's answer to reduce the list of points that need checking to a much smaller subset

    0 讨论(0)
提交回复
热议问题