- Getting Started with Hazelcast
- Mat Johns
- 630字
- 2021-08-06 16:56:52
Searching and indexing
In moving towards creating clean key/value-based storage, we may find that we have lost some of the extra searching capabilities that traditional databases offer. Mainly that we now can't find records within a dataset without knowing the primary key to that entry. However, fear not, as Hazelcast provides similar capabilities for searching its maps by predefined indexes. These can be either ordered (ascending) or unordered, depending on our particular data needs. But be aware that indexing doesn't come for free; the internal lookup table used to provide the quick searching on reads is maintained as we make changes to the map; this will add latency to every write operation to that namespace.
So firstly, let's create a new plain old Java object (POJO) to represent a city.
import java.io.Serializable; public class City implements Serializable { private String name; private String country; private int population; public City(String name, String country, int population) { this.name = name; this.country = country; this.population = population; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public int getPopulation() { return population; } public void setPopulation(int population) { this.population = population; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; City other = (City) o; if (!this.country.equals(other.country)) return false; if (!this.name.equals(other.name)) return false; return true; } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + country.hashCode(); return result; } @Override public String toString() { return String.format( "City{name='%s', country='%s', population=%d}", name, country, population); } }
As you can see, we have created our City
class to implement Serializable
so that it can be correctly persisted within Hazelcast. We have also implemented the equals()
and hashCode()
methods so the required behavior is ensured. Additionally, a toString()
method has been added for debugging convenience.
Using this, we can update our previous map example to use our new city POJO. One major change from the previous example is that in order to access the additional indexing functionally, we have to use the Hazelcast specific IMap
interface rather than the standard Java Map
that we used before.
In order to search the map, we need to provide a Predicate
object to filter on. One such implementation of this is that we can use SqlPredicate
, which provides us with the ability to use a SQL-like syntax to describe the filter.
IMap<String, City> capitals = hz.getMap("capitals"); capitals.addIndex("name", false); capitals.addIndex("population", true); capitals.put("GB", new City("London", "GB", 8174100)); capitals.put("FR", new City("Paris", "FR", 2268265)); capitals.put("US", new City("Washington DC", "US", 601723)); capitals.put("AU", new City("Canberra", "AU", 354644)); Collection<City> possibleLondons = capitals.values( new SqlPredicate("name = 'London'"));); System.err.println(possibleLondons); Collection<City> largeCities = capitals.values( new SqlPredicate("population > 1000000")); System.err.println(largeCities);
The supported syntax is very much a limited subset of SQL, but should feel familiar.
- AND/OR: For combining multiple expressions
- =, !=, <, <=, >, >=: For expression comparison
- LIKE: For simple string pattern matching expressions
- IN: For providing a defined list of sought values
- BETWEEN: For providing a range of sought numeric values
- NOT: Can be used as a prefix to negate the expression
The preceding functions are used in the following code:
country = 'GB' AND population BETWEEN 10000 AND 100000 country NOT IN ('GB', 'FR') name LIKE 'L%'
If you would prefer to construct your query more programmatically, we can use a JPA-like criteria API provided by PredicateBuilder
, or more manually using various helper methods in Predicates
. We could use the following alternative code in place of our previous SQL based predicates:
EntryObject c = new PredicateBuilder().getEntryObject(); Predicate londonPredicate = c.get("name").equal("London"); Collection<City> possibleLondons = capitals.values(londonPredicate); System.err.println(possibleLondons); Predicate largeCityPredicate = Predicates.greaterThan( Predicates.get("population"), 1000000); Collection<City> largeCities = capitals.values(largeCityPredicate); System.err.println(largeCities);
- Learn Blockchain Programming with JavaScript
- 零基礎玩轉區(qū)塊鏈
- CentOS 7 Server Deployment Cookbook
- Bootstrap Essentials
- TypeScript實戰(zhàn)指南
- Hands-On Swift 5 Microservices Development
- Spring Boot企業(yè)級項目開發(fā)實戰(zhàn)
- Android應用案例開發(fā)大全(第二版)
- Building Microservices with .NET Core
- Go語言精進之路:從新手到高手的編程思想、方法和技巧(2)
- 案例式C語言程序設計實驗指導
- Spring技術內幕:深入解析Spring架構與設計原理(第2版)
- C陷阱與缺陷
- 深入實踐DDD:以DSL驅動復雜軟件開發(fā)
- PowerDesigner 16 從入門到精通