Skip to content

Aggregation of nearBy + group (distinct) + paging  #4782

Closed

Description

@ranhsd

Hi, I have some requirement to create query with the following constraints :

  1. Present all objects which near by specific location coordinates
  2. Use distinct values to avoid duplicates
  3. Limit the results to 20 and if there are more than 20 skip the first 20

First, I tried to use the regular find and created the following GeoQuery

          var oQuery = new Parse.Query("ItemLocation");
            oQuery.withinMiles("location",currentLocationGeoPoint, 2.0);
            oQuery.limit(20);
            if (request.params.skip) {
                oQuery.skip(request.params.skip);
            }
            let results = await oQuery.find();

The above query fulfil requirements 1 and 3 but not requirement 2

Then I tried to use distinct and created the following query:

            var oQuery = new Parse.Query("ItemLocation");
            oQuery.withinMiles("location",currentLocationGeoPoint, 2.0);
            oQuery.limit(20);
            if (request.params.skip) {
                oQuery.skip(request.params.skip);
            }
            let results = await oQuery.distinct("itemId");

Now I don't see duplicates anymore and I am really get items which are 2 miles near by the location but the limit/skip is not working so this query fulfil requirements 1 and 2 but not 3

Finally, I tried to use aggregate and created the following query:

            var oQuery = new Parse.Query("ItemLocation");
            var pipeline = [
                {geoNear: {
                    near: [ currentLocation.longitude , currentLocation.latitude ],
                    distanceField: "location",
                    maxDistance: 2
                }},
                { group: {objectId: '$itemId'} },
                {skip: request.params.skip || 0, limit: 20}
            ];


            let results = await oClosetsNearByQuery.aggregate(pipeline);

I've noticed that I get exactly what I need but I am not sure that I should do that. First I tried to use geoJSON coordinate in the near but it seems like that parse-server still do not support GeoJSON so I switched back to the legacy coordinates and it worked. Also, I've noticed that the distanceField can be anything and it not must be equal to the name of my GeoPoint field in the collection.

So I wanted to know 3 things:

  1. If the aggregate query that I wrote above is fine?
  2. If there is another way to achieve the same results by using one query only
  3. When GeoJSON will be supported?

@dplewis or @flovilmart can you provide some inputs? or maybe someone else can provide?

Thanks!

Activity

  1. flovilmart commented on May 23, 2018

    @flovilmart
    Contributor

    I cannot speak for 1 and 2, but if the data you get is fine, that's what you should use. And 2, you need to use distinct which imposes using a pipeline.

    When GeoJSON will be supported?

    It's gonna be supported when a contributor will need it enough to write the feature! Note that polygons are fully supported now.

  2. dplewis commented on May 23, 2018

    @dplewis
    Member

    When GeoJSON will be supported?

    I opened a PR #4069 for it a while ago but closed it. I can add it back this weekend.

  3. flovilmart commented on May 23, 2018

    @flovilmart
    Contributor

    @dplewis let's see :)

  4. dplewis commented on May 23, 2018

    @dplewis
    Member

    @ranhsd Distinct returns an array not a cursor. It can't be used with cursor operators like limit / skip. To make it work you have to replace the current code with aggregate $group and build a pipeline. But that defeats the purpose of having Distinct as a standalone query option.

    I'm surprised that it worked using withinMiles.

  5. ranhsd commented on May 23, 2018

    @ranhsd
    ContributorAuthor

    Hi @dplewis Please have a look on the third example that I posted. There I am doing everything in one query. The only thing that I wanted to know if this is ok or not

  6. dplewis commented on May 23, 2018

    @dplewis
    Member

    I've noticed that I get exactly what I need

    It looks good to me. You get what you need right?

    First I tried to use geoJSON coordinate in the near

    If you really need to add geoJSON to near, just add 2dsphere index to the field. Your points in the database doesn't have to be geoJSON. (2dsphere isn't supported in parse yet for geopoints).

    Keeping it the way you have won't break in the future.

    I've noticed that the distanceField can be anything and it not must be equal to the name of my GeoPoint field in the collection.

    This will create an entirely new field to hold calculated data. You can just ignore it if you want and put any field name.

  7. ranhsd commented on May 24, 2018

    @ranhsd
    ContributorAuthor

    Hi @dplewis thanks,

    Yes I get what I need.
    I need to add the index manually right? If I add it I will still be able to use Parse GeoPoint ?

    Thanks,
    Ran.

  8. indiandragon commented on May 29, 2018

    @indiandragon

    Hi guys,

    @ranhsd @dplewis

    Just to note : when I added 2dsphere index to legacy coordinates (as used in Parse), it resulted in
    MongoErrors with result not being found. Generic 2d index worked perfectly for legacy coordinates.

    MongoDB : 3.4.9
    Parse Server : 2.6.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions