I have a Location Service with an endpoint that returns people near from a given user:

GET /users/near?user=7455 

      "userId": 1214,
      "location" : [2134983, 89384]
    //more users

On the other hand, I have a Visits Service that manages the visits between users:

      "userVisitor" : 7155,
      "userVisited" : 8778,
      "date" : "1991/02/10"       

Now, from the API Gateway, I need to fetch users near from a given user and that haven't been visited yet by him. Something like this (pseudocode):

user = 7758
users = LocationService.getNearUsers(user)
output = []
for (userTarget in users) {
    if VisitsService.userHasNotVisited(user, userTarget) {
return output

Is it a good approach? Or should I implement an endpoint in Visits Service that filters the non-visited-yet users from a given users list? Something like this:

GET /visits/filter/nonvisited?visitor=7758&targets=1277,3681,3586

and do something like:

user = 7758
users = LocationService.getNearUsers(user)
output = VisitsService.filterNonVisited(user, users)
return output

Which is the better solution?

  • depends how the services work
    – Ewan
    Jul 24, 2017 at 9:55
  • I am to develope both services. They don't exist yet
    – Héctor
    Jul 24, 2017 at 9:57
  • if they are all reading out of the same relational db then service.GetExactyWhatIWantAndNothingElse is going to be quickest. But if you are doing several things with the same data on the page a more generic approach will save you io calls. You have to be a bit hollistic about these things. But I would say the looping example you give is rarely the best
    – Ewan
    Jul 24, 2017 at 10:00
  • Each service has its own no-sql database. So, I should choose the second solution, right?
    – Héctor
    Jul 24, 2017 at 10:02
  • nosql dbs dont seem suited to your services. how are you doing nearest()? basically there isnt enough info, for me, to give you a specific 'this is best' answer.
    – Ewan
    Jul 24, 2017 at 10:07

1 Answer 1


This is really a question of how you organise your data.

Your overall query 'Get users which have not visited user x within this area' is very relational.

You can imagine the table setup, with users, location and a many to many visits table which you can query all in one go.

Select * from users 
left join (select visits where userId= Y) 
user.location is near X, 
visits.id = null

or something. You would then be asking yourself if this was worth bothering with or whether a combination of get users and get visits could achieve the same effect in a reasonable time an be more generic.

However if you have a NoSQL setup like you have indicated you are a bit stuck with your a visits because you cant really do the relational where clause.

The NoSql solution requires you group the data by a single key. Putting all the visits in a single document, possibly the same user document you are using for everything else.

This means you can achieve your result in two fast queries, but have to do the filtering in code.

The downside is that if each user has many visits you have to retrieve a lot of data you don't need. Additionally your inclusion of a date field suggests you might want to do further filtering.

One way to work around this problem is to introduce a new object which collects together the data you want.

Lets say the use case is a salesman visiting a city and he wants to visit all the customers in the city once unless he's visited them within a month.

You could generate that check list once as a slow operation, save it in a single document as a CityVisit and then have the user remove items from it each time they make a visit. Then its a quick call to retrieve the list and it can be thrown away when done.

  • Thank you! This is a better approach. I think it would be nice to use geographic features from MariDB to perform the nearby query. Thanks again.
    – Héctor
    Jul 24, 2017 at 11:21
  • it should be noted that you can do the same kind of geospatial indexing on a relational db.
    – Ewan
    Jul 24, 2017 at 11:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.