core.bones.spatial

Module Contents

Classes

SpatialBone

Allows to query by Elements close to a given position.

Functions

haversine(lat1, lng1, lat2, lng2)

Calculates the distance between two points on Earth given by (lat1,lng1) and (lat2, lng2) in Meter.

core.bones.spatial.haversine(lat1, lng1, lat2, lng2)

Calculates the distance between two points on Earth given by (lat1,lng1) and (lat2, lng2) in Meter. See https://en.wikipedia.org/wiki/Haversine_formula

Returns

Distance in Meter

class core.bones.spatial.SpatialBone(*, boundsLat: Tuple[int, int], boundsLng: Tuple[int, int], gridDimensions: Tuple[int, int], **kwargs)

Bases: viur.core.bones.base.BaseBone

Allows to query by Elements close to a given position. Prior to use, you must specify for which region of the map the index should be build. This region should be as small as possible for best accuracy. You cannot use the whole world, as no boundary wraps are been performed. GridDimensions specifies into how many sub-regions the map will be split. Results further away than the size of these sub-regions won’t be considered within a search by this algorithm.

Example:

If you use this bone to query your data for the nearest pubs, you might want to this algorithm to consider results up to 100km distance, but not results that are 500km away. Setting the size of these sub-regions to roughly 100km width/height allows this algorithm to exclude results further than 200km away on database-query-level, therefore drastically improving performance and reducing costs per query.

Example region: Germany: boundsLat=(46.988, 55.022), boundsLng=(4.997, 15.148)

type = spatial
getGridSize(self)
Returns

the size of our sub-regions in (fractions-of-latitude, fractions-of-longitude)

Return type

(float, float)

isInvalid(self, value: Tuple[int, int]) Union[str, bool]

Tests, if the point given by ‘value’ is inside our boundaries. We’ll reject all values outside that region. :param value: (latitude, longitude) of the location of this entry. :return: An error-description or False if the value is valid :rtype: str | False

singleValueSerialize(self, value, skel: SkeletonInstance, name: str, parentIndexed: bool)
singleValueUnserialize(self, val)
parseSubfieldsFromClient(self)
isEmpty(self, rawValue: Any)
getEmptyValue(self) Tuple[float, float]

If you need a special marker for empty, use 91.0, 181.0. These are both out of range for Latitude (-90, +90) and Longitude (-180, 180) but will be accepted by Vi and Admin

singleValueFromClient(self, value: Dict, skel: str, name: str, origData: Dict)

Reads a value from the client. If this value is valid for this bone, store this value and return None. Otherwise our previous value is left unchanged and an error-message is returned.

Parameters
  • name – Our name in the skeleton

  • valueUser-supplied request-data

buildDBFilter(self, name: str, skel: viur.core.skeleton.SkeletonInstance, dbFilter: viur.core.db.Query, rawFilter: Dict, prefix: Optional[str] = None) viur.core.db.Query

Parses the searchfilter a client specified in his Request into something understood by the datastore. This function must:

  • Ignore all filters not targeting this bone

  • Safely handle malformed data in rawFilter

    (this parameter is directly controlled by the client)

For detailed information, how this geo-spatial search works, see the ViUR documentation.

Parameters
  • name – The property-name this bone has in its Skeleton (not the description!)

  • skel – The viur.core.db.Query this bone is part of

  • dbFilter – The current viur.core.db.Query instance the filters should be applied to

  • rawFilter – The dictionary of filters the client wants to have applied

Returns

The modified viur.core.db.Query

calculateInternalMultiQueryLimit(self, dbQuery: viur.core.db.Query, targetAmount: int)

Tells viur.core.db.Query How much entries should be fetched in each subquery.

Parameters

targetAmount – How many entries shall be returned from db.Query

Returns

The amount of elements db.Query should fetch on each subquery

customMultiQueryMerge(self, name, lat, lng, dbFilter: viur.core.db.Query, result: List[viur.core.db.Entity], targetAmount: int) List[viur.core.db.Entity]

Randomly returns ‘targetAmount’ elements from ‘result’

Parameters
  • name

  • lat

  • lng

  • dbFilter – The db.Query calling this function

  • result – The list of results for each subquery we’ve run

  • targetAmount – How many results should be returned from db.Query

Returns

List of elements which should be returned from db.Query

setBoneValue(self, skel: SkeletonInstance, boneName: str, value: Any, append: bool, language: Union[None, str] = None) bool

Set our value to ‘value’. Santy-Checks are performed; if the value is invalid, we flip our value back to its original (default) value and return false.

Parameters
  • skel – Dictionary with the current values from the skeleton we belong to

  • boneName – The Bone which should be modified

  • value – The value that should be assigned. It’s type depends on the type of that bone

  • append – If true, the given value is appended to the values of that bone instead of replacing it. Only supported on bones with multiple=True

Returns

Wherever that operation succeeded or not.