【问题标题】:What is the equivalent of mongoengine.GeoPointField in motorengine to perform near queries?什么是 mongoengine.GeoPointField 在 motorengine 中执行近距离查询的等价物?
【发布时间】:2018-03-10 23:31:20
【问题描述】:

我有以下型号: class DbObjectWithCoordinates(Document): coordinates = GeoPointField() # this used to work with mongengine

我使用mongoengine.GeoPointField 执行查询,例如查找给定坐标附近的所有对象:

user_coordinates = user.coordinates
objects_of_interest = DbObjectWithCoordinates.objects(coordinates__near=user_coordinates, coordinaes_max_distance=3)

但是 GeoPointField 字段在 motorengine 中不可用。 是否可以在 motorengine 中定义对象并使用这样的查询?如果没有,这种用例是否有解决方法?

【问题讨论】:

    标签: mongodb tornado tornado-motor motorengine


    【解决方案1】:

    我认为实现地理点字段会相当容易。下面是非常简单的实现,当然它不是一个完整的。

    from motorengine.fields import *
    from pymongo import GEOSPHERE, GEO2D
    from motorengine.query.base import QueryOperator
    from motorengine.utils import serialize, deserialize
    
    class GeoPointField(BaseField):
    
        def __init__(self, *args, **kwargs):
            super(GeoPointField, self).__init__(*args, **kwargs)
    
        def validate(self, lst):
            if not isinstance(lst, (list, )):
                return False
            return True
    
        def to_son(self, lst):
            longitude = lst[1]
            latitude = lst[0]
            value = {"type": "Point", "coordinates": [latitude, longitude]}
            return value
    
        def from_son(self, jsn):
            valued = jsn
            longitude = valued.get("coordinates")[1]
            latitude = valued.get("coordinates")[0]
            return [latitude, longitude]
    
    class GeoNearOperator(QueryOperator):
    
        def to_query(self, field_name, value):
            return {
                    field_name: {
                          "$near": {
                             "$geometry": {
                               "type": "Point",
                               "coordinates": list(value[0])
                             },
                             "$minDistance": value[1]
                          }
                       }
                    }
    
        def get_value(self, field_name, raw_value):
            return raw_value
    
    
    class GeoSphearNearOperator(QueryOperator):
    
        EARTH_RADIOUS = 3963.2
    
        def to_query(self, field_name, value):
            return {
                     field_name: {
                      "$geoWithin": {
                           "$centerSphere": [list(value[0]),
                                             value[1]/self.EARTH_RADIOUS]
                         }
                     }
                   }
    
        def get_value(self, field_name, raw_value):
            return raw_value
    
    class Events(MotorEngineDocument):
    
        __indexes__ = [('location', GEOSPHERE)]
    
        name = StringField(required=True)
        tid = StringField(required=True)
        event_on = DateTimeField(required=True)
        location = GeoPointField(required=True)
    
    
        @classmethod
        async def nearby(cls, lat, lon, radious, limit=10, skip=0):
            results = await cls.objects.limit(limit).skip(skip)\
                .filter(location__around=[(lat, lon), radious])\
                .find_all()
            return results
    

    但您需要确保在地理查询之前正确更新发动机运算符。

    from motorengine.query_builder.transform import OPERATORS
    OPERATORS.update({
       "near": GeoNearOperator,
       "around": GeoSphearNearOperator,
       "search": TextSearch
    })
    

    【讨论】:

    • 我很高兴
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 2012-10-29
    • 2012-01-02
    • 2018-12-17
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    相关资源
    最近更新 更多