Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB $geoNear aggregation pipeline (using query option and using $match pipeline operation) giving different no of results

I am using a $geoNear as the first step in the aggregation framework. I need to filter out the results based on "tag" field and it works fine but I see there are 2 ways both giving different results.

Sample MongoDB Document


    {
      "position": [
        40.80143,
        -73.96095
      ],
      "tag": "pizza"
    }

I have added 2dsphere index to the "position" key


    db.restaurants.createIndex( { 'position' : "2dsphere" } )

Query 1

uses $match aggregration pipeline operation to filter out the results based on "tag" key

    db.restaurants.aggregate(
      [
       {
           "$geoNear":{

               "near": { type: "Point", coordinates: [ 55.8284,-4.207] },
               "limit":100,
               "maxDistance":10*1000,
               "distanceField": "dist.calculated",
               "includeLocs": "dist.location",
               "distanceMultiplier":1/1000,
               "spherical": true
        }
       },{
           "$match":{"tag":"pizza"}
       },

       {
          "$group":{"_id":null,"totalDocs":{"$sum":1}}
       }
      ]
    );

Query 2

Uses query inside the $geoNear aggregation operation to filter results based on "tag" key

    db.restaurants.aggregate(
      [
       {
           "$geoNear":{
               "query" : {"tag":"pizza"}
               "near": { type: "Point", coordinates: [ 55.8284,-4.207] },
               "limit":100,
               "maxDistance":10*1000,
               "distanceField": "dist.calculated",
               "includeLocs": "dist.location",
               "distanceMultiplier":1/1000,
               "spherical": true
        }
       },
       {
          "$group":{"_id":null,"totalDocs":{"$sum":1}}
       }
      ]
    );

The grouping option is just to get the count of documents returned by both the queries.

The totalDocs returned by both queries seem to be different.

Can someone explain me the differences between both the queries ?

like image 349
Akshay Mehta Avatar asked Feb 11 '17 08:02

Akshay Mehta


People also ask

Which of these aggregation pipeline stages will allow you to process multiple aggregation pipeline in a single phase?

aggregate() method. Creates new documents in a sequence of documents where certain values in a field are missing. Returns literal documents from input values. Processes multiple aggregation pipelines within a single stage on the same set of input documents.

Which pipeline is used for aggregation in MongoDB?

Mongoid exposes MongoDB's aggregation pipeline, which is used to construct flows of operations that process and return results. The aggregation pipeline is a superset of the deprecated map/reduce framework functionality.

What are the differences between using aggregate () and find ()? In MongoDB?

With aggregate + $match, you get a big monolithic BSON containing all matching documents. With find, you get a cursor to all matching documents. Then you can get each document one by one.

When used with $match what operation must be used at the beginning of the pipeline?

To use $text in the $match stage, the $match stage has to be the first stage of the pipeline.


2 Answers

Few assumptions:-
1. Assume there are 300 records that match based on the location.
2. Assume first set of 100 results do not have tag pizza. The rest 200 documents (101 to 300) have tag pizza

Query 1:-

  • There are 2 pipeline operations $geoNear and $match
  • The output of $geoNear pipeline operation is the input to $match pipeline operation
  • $geoNear finds max of 100 results (limit we have specified) based on the location sorted by nearest to far distance. (Note here that the 100 results retured are purely based on the location. So these 100 results do not contain any document with tag "pizza")
  • These 100 results are sent to the next pipeline operation $match from where the filtering happens. But since the first set of 100 results did not have tag pizza, the output is empty

Query 2:-

  • There is only 1 pipeline operation $geoNear
  • There is a query field included in the $geoNear pipeline operation $geoNear finds max of 100 results (limit we have specified) based on the location sorted by nearest to far distance and the query tag=pizza
  • Now here the results from 101 to 200 are returned as output as the query is included within the pipeline operation $geoNear. So in simple sentence we say, find all documents with location [x,y] with tag=pizza.

P.S : - The $group pipeline stage is added just for getting the count and hence have not written about it in the explaination

like image 139
Akshay Mehta Avatar answered Oct 31 '22 14:10

Akshay Mehta


// If you have to apply multiple criteria to find locations then this query might helpful

 const userLocations = await userModel.aggregate([
            {
                $geoNear: {
                    near: { type: "Point", coordinates: [data.lon1,data.lat1] 
                      },//set the univercity points
                    spherical: true,
                    distanceField: "calcDistance",
                    // maxDistance: 2400,//25km 
                    "distanceMultiplier": 0.001,
                   
                }
            },
            { $unwind: "$location" }, 
            { $match: {
                "location": {
                  $geoWithin: {
                    $centerSphere: [
                      [ 73.780553, 18.503327], 20/ 6378.1        //check the user point is present here
                    ]
                  }
                }
              }},
        

        ])
like image 42
Akshay Dhawle Avatar answered Oct 31 '22 14:10

Akshay Dhawle