官术网_书友最值得收藏!

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);
主站蜘蛛池模板: 普兰店市| 巴里| 淅川县| 新沂市| 普兰店市| 绥江县| 河北区| 东乡族自治县| 张北县| 峨山| 卓尼县| 浙江省| 科技| 晴隆县| 汕尾市| 孝义市| 罗田县| 大同县| 玉溪市| 安义县| 云南省| 宜都市| 海淀区| 栾川县| 昆明市| 福贡县| 潢川县| 元氏县| 十堰市| 稻城县| 商丘市| 南漳县| 贡觉县| 枣阳市| 商南县| 都匀市| 丰都县| 芒康县| 昭觉县| 抚州市| 江西省|