I’m trying to implement a “nearby” filter with Xodus, having this code:
AtomicReference<EntityIterable> referenceToScope = ...; PropertyNearbyCondition propertyNearbyCondition = (PropertyNearbyCondition) entityCondition; String propertyName = propertyNearbyCondition.propertyName(); Double longitude = propertyNearbyCondition.longitude(); Double latitude = propertyNearbyCondition.latitude(); Double distance = propertyNearbyCondition.distance(); EntityIterable entities = referenceToScope.get().intersect(txn.findWithProp(entityType, propertyName)); List<Entity> entityList = new ArrayList<>(); entities.forEach(entity -> { GeoPoint reference = (GeoPoint) entity.getProperty(propertyName); double instantaneousDistance = MathHelper.distFrom(latitude, longitude, reference.getLatitude(), reference.getLatitude()); if (distance >= instantaneousDistance) { entityList.add(entity); } }); EntityIterable scoped = referenceToScope.get().intersect(build(entityList));
EntityIterable build(List<Entity> entityList) { // TODO: Build a new EntityIterable from the entityList }
The algorithm may not be the best, but, the main question here is how to build a new EntityIterable
based from multiple Entity objects? Is that possible?
My solution to basically collect “nearby” entities is to iterate over all entities with the custom GeoPoint
property then for each Entity found, comparing the distance of its GeoPoint property and if that is a hit then all these entities should be collected into one EntityIterable.
How do you build a EntityIterable
from a list of Entity
objects?
UPDATE:
Explaining how this works step-by-step:
This code below gets all the entities with the given property name, e.g. geoLocation
EntityIterable entities = referenceToScope.get().intersect(txn.findWithProp(entityType, propertyName));
Then for all the entities with such geoLocation property for example iterate over it to compute if it meets the distance target:
List<Entity> entityList = new ArrayList<>(); entities.forEach(entity -> { // compute the distance target });
Adding the entity to the new List
if it meets the target.
From here what needs to be done is to either remove all entities in the EntityIterable entities
which does not equal to the ID’s of the matched entities in the entityList
OR to intersect these matched entities to referenceToScope.get()
and not to EntityIterable entities
(just to avoid confusion, this entities
iterable is a just a temp one)
Advertisement
Answer
Here’s how to solve this:
entities.forEach(entity -> { GeoPoint reference = (GeoPoint) entity.getProperty(propertyName); double instantaneousDistance = MathHelper.distFrom(latitude, longitude, reference.getLatitude(), reference.getLatitude()); if (distance < instantaneousDistance) { referenceToScope.set(referenceToScope.get().minus(txn.getSingletonIterable(entity))); } });
This will effectively remove all entities that fails to match the target distance.