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

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);
主站蜘蛛池模板: 丹寨县| 东平县| 德江县| 中西区| 都安| 乌恰县| 东平县| 三亚市| 邢台县| 景洪市| 开鲁县| 洛阳市| 大姚县| 图木舒克市| 淳化县| 嘉禾县| 离岛区| 昌平区| 密山市| 海林市| 醴陵市| 江川县| 格尔木市| 浮山县| 平顺县| 南部县| 兴仁县| 合川市| 衡阳县| 全椒县| 吉林市| 武清区| 航空| 广宁县| 桂阳县| 齐齐哈尔市| 安福县| 临漳县| 广元市| 虹口区| 尚志市|