如何在MongoDB的$geonear聚合管道中按其他字段排序

1 投票
1 回答
1429 浏览
提问于 2025-04-18 10:52

我的数据集合是这个格式。

{
    "_id" : ObjectId("52e5f94d83b45407f959e7ff"),

    "latlng" : {
        "coordinates" : [
            85.29035240000007,
            27.6663671
        ],
        "type" : "Point"
    },
    "name" : "Sujit Maharjan",
    "updates" : [
        {
            "status" : "I want to #buy 5 kg of tomatoes.",
            "picture" : [ ],
            "parent_tweet_id" : "0",
            "deleted" : 1,
            "tweet_id" : "428578269169205248",
            "time_stamp" : 1391015996
        }
        {
            "status" : "I want to #start #milk business who can help me ?",
            "picture" : [ ],
            "parent_tweet_id" : "0",
            "deleted" : 0,
            "tweet_id" : "108fd43a-7efa-404d-800d-0c30a5da06e5",
            "time_stamp" : 1391955084
        },
        {
            "status" : "@SantoshGhimire @bhanduroshan Connect to us for  #Dairy business",
            "picture" : [ ],
            "parent_tweet_id" : "432503201968168960",
            "deleted" : 1,
            "tweet_id" : "432517594026082304",
            "time_stamp" : 1391955208
        },
        {
            "status" : "@bhanduroshan Did you get my message ?",
            "picture" : [ ],
            "parent_tweet_id" : "432502654154334208",
            "deleted" : 0,
            "tweet_id" : "432788670463377408",
            "time_stamp" : 1392019838
        },
        {
            "status" : "this is tweet with images @foodtradeHQ http://t.co/3eL1351HWf",
            "picture" : [
                "http://pbs.twimg.com/media/BgLZ4YaCUAAsFTJ.jpg"
            ],
            "parent_tweet_id" : "0",
            "deleted" : 1,
            "tweet_id" : "433148076820156417",
            "time_stamp" : 1392105574
        }
    ]
}

现在我需要查询用户在某个特定范围内的更新,并按照更新的时间进行排序。

为此,我使用了聚合管道,但$geonear查询会根据距离进行排序,并限制结果的数量。

这是我在Python中写的管道。

    geo_search = {"near": [float(self.lng), float(self.lat)],
                               "distanceField": "distance",
                                "includeLocs": "latlng",
                                "uniqueDocs": True,
                                "spherical":True,
                                "limit":100,  # this will cut off the possible results, and complexity increasing in increasing this number
                            }



    pipeline = []

    final_query = {"$and":query_string}

    if len(query_string)>0:
        geo_search['query'] = final_query


    geo_search['maxDistance'] = 0.01261617096

    geo_near = {
                    "$geoNear": geo_search
                  }


    pipeline.append(geo_near)

1 个回答

2

使用$geoNear这个聚合管道阶段,基本上就是进行一种标准的“近球”或“附近”的查询,但它会在结果文档中添加一个额外的字段,这个字段是为了distanceField所需要的。

这个步骤必须是管道的第一个阶段,这样它才能使用索引:

 collection.aggregate([
     { "$geoNear": {
         "near": [ float(self.lng), float(self.lat) ],
         "maxDistance": 0.01261617096,
         "distanceField": "distance",
         "includeLocs": "latlng",
         "uniqueDocs": True,
         "spherical":True,
         "query": {
             "updates.time_stamp": {
                 "$gte": timestamp_cutoff
             }
         },
         "limit":100
     }},
     { "$sort": { "other": 1, "distance": 1 } }
])

在管道的后续步骤中,现在会有一个额外的字段,就是在“distanceField”中定义的那个字段。为了获取最近的结果,你需要把这个字段传递给$sort。你可以传递任何你想要排序的内容,因为这就是这个管道阶段的作用。

你可以对结果进行任何操作,包括添加其他阶段,比如$match等等。当然,如果其他信息与初始结果相关,那么你可以在$geoNear中使用“query”选项。

实际上,为了实现你想要的结果,你需要通过在“query”中使用某些条件来“限制”可能匹配的文档,就像上面展示的那样。所以返回的“最近”文档仅仅是那些符合额外条件的文档。

撰写回答