Calculating distance in Atlas Search

Hi everyone,

I am struggling to find a way to calculate distance between a user point (the user location) and points in a collection within Atlas Search. Neither “near” nor “geoWithin” offer any way to calculate distance in a 2dsphere (unlike $geoNear in aggregation). My app needs to conduct both text search (on fields like book title, description) and geospatial queries (proximity to user), and Atlas search seems to be capable to do both in one query, but there is no option to calculate the distance. Am I missing something as it is a substantial disadvantage? Many thanks for all help.

Hi @Gueorgui_58194 ,

Thats an interesting question. i saw that near operator uses pivot and distance to compute score for geo data :

score = pivot /pivot + distance

If you use pivot as 1 you might be able to take a score and figure out a distance for each document.

score(pivot +distance)=pivot
score*pivot + score*distance = pivot
distance = (pivot - score*pivot)/score

Thanks
Pavel

That’s very clever Pavel. Thanks very much. I will try it now.

1 Like

Hi Pavel,

Following up on this, I gave it a try but the problem is that the score for my searches is a combination of the scores for different clauses (not only the “near” operator in Atlas search). I don’t see any way I can extract the score just for “near”. I ended up calculating the distance using longitude and latitude in my app (rather than the database), which comes up pretty accurate. This does not completely meet my use case as I am not able to do a pure distance sort on the database (I can do it in the app, but that would mean getting all the results from the db, doing the sort and then getting the relevant page of the results). If the search is purely on distance, Mongo sorts automatically, but I cannot rely on this when the search includes other parameters. I think it would be good to expose the distance calculated by Mongo in the API (since it is done anyway by Mongo when using near or geoWithin in Atlas search).

Thanks very much for loking into this.

Kind regards,
Gueorgui

Hi @Gueorgui_58194 ,

I’ve raised this with our Product managers for search.

CC: @Marcus

Thanks for sharing
Pavel

There is this feature request you can vote on to be notified when we release this feature.

Hello,

Also I am currently struggling with this. My idea currently is this:
→ Use “near” to calculate the distance and use the “function”-option in the “near”-score to calculate the distance like this: distance = (pivot - score*pivot)/score. Is this possible? Make sure that this is an integer value and add this number as “score” for the “near”
→ The other clause i use is a simple “text” to calculate the search match which is a value between 0-1. Am I correct?

If I understood everything correctly, my final score should now consist of the integer value which is my distance and the desimals would be the final score.

I ended up using a hybrid solution where I use the $search for filtering my query and calculating the “score” with using only “near”. Then on my aggregate, I use “$addFields” to calculate the distance knowing the “pivot” and the “score”. After that I have my other addFields to add more fields required to sort my query and finally I use normal “$sort”-stage and “$limit” and return my results.

I was hoping to use $search to calculate also “Text match” for a few fields on my item but it seems like I need to wait for updates for $search to be able to solve my use case. I think I will go with Elastic search for now and connect my collection to elastic search and then give mongo atlas another try when their search index offers all the required features.

In the end, compared to not using “$search” at all, I am left with a much more efficient solution to filter and calculate the distance than “$geoNear” that I was forced to use before. $geoNear scans the whole collection always and therefore querying more than 200k of items with this method resulted in horribly performance queries that were too much for the database cluster.

-Sakarias