一个高性能的java 集合搜索工具。使用它,可以用类似sql的语句对Java集合进行检索,且延迟极低。
作者对其优点的描述是:每秒百万次的查询,查询延迟在微秒范围内,转移数据库的查询带宽,扩展应用层,是数据库查询速度的千倍,即使在低端硬件上。关于cqengin和传统java 集合查询的性能比较dzone.com: Comparing the search performance of CQEngine with standard Java collections。相关概念1索引cqengin 通过在对象的字段上创建索引解决扩展性和延迟问题。在一个对象集合中,简单索引可以被添加到任意数量的单个字段上,使得基于这些属性的查询都是O(1)的时间复杂度对一个对象字段,可以添加多个索引,每个索引对应不同的查询,例如,字段相等,字段值在某个范围内,字符串字段以某个串开始等复合索引针对多个字段cqengin同时支持嵌套索引,类似于sql语句:"WHERE color = 'blue' AND(NOT(doors = 2 OR PRice > 53.00))"2属性cqengin需要访问对象字段以便建立索引,并检索这些字段的值,它不是通过反射,而是采用 attributes來实现这一目的。attribute是一个更强大的概念,它是可以读取pojo某个字段值的对象访问器。如下语句对一个Car对象定义attribute。它能够访问car对象的carId.
public static final Attribute<Car, Integer> Car_ID = attribute("carId", Car::getCarId);
第一个参数是可选的,但是官方文档里推荐这种作法。另外,在Car类里定义上述attribute 是通常的作法,但这并不是强制,跟一个类相关的attribute可以定义在任何一个地方。多值attribute,访问对象的集合字段,如下图,features是一个list<String>类型字段
public static final Attribute<Car, String> FEATURES = attribute(String.class, "features", Car::getFeatures);
给定一个对象,attribute被要求返回一个值,多数情况下,这个值是一个对象的字段值,同时,还可以是应用于其他字段或外部数据的函数的返回值。如:public static final Attribute<Car, Boolean> IS_DIRTY = attribute("dirty", car -> car.description.contains("dirty"));
如下attribute能够访问每个car的serviceLocation。public static final Attribute<Car, String> SERVICE_LOCATIONS = new MultiValueAttribute<Car, String>() { public List<String> getValues(Car car, QueryOptions queryOptions) { return CarServiceManager.getServiceLocationsForCar(car); }};
3.query
CQengine使用query来检索对象。同时可以使用sql语句或者CQN(cqengine native)
通过retrieve方法获取结果值,
以下是一个完整的示例:
@Servicepublic class searchService { public static final Attribute<Car, Integer> Car_ID = attribute("carId", Car::getCarId); public static final Attribute<Car, String> DESCRIPTION = attribute("carDesc", Car::getDescription); public static final MultiValueAttribute<Car, String> FEATURES = attribute(String.class, "features", Car::getFeatures); //使用query public String test1() { StringBuffer sbBuffer=new StringBuffer(); IndexedCollection<Car> cars = new ConcurrentIndexedCollection<Car>(); //添加对象 cars.add(new Car(1, "ford focus", "great condition, low mileage", Arrays.asList("spare tyre", "sunroof"))); cars.add(new Car(2, "ford taurus", "dirty and unreliable, flat tyre", Arrays.asList("spare tyre", "radio"))); cars.add(new Car(3, "honda civic", "has a flat tyre and high mileage", Arrays.asList("radio"))); //添加索引 cars.addIndex(NavigableIndex.onAttribute(Car_ID)); cars.addIndex(SuffixTreeIndex.onAttribute(DESCRIPTION)); cars.addIndex(HashIndex.onAttribute(FEATURES)); //创建查询 Query<Car> query1 = and(startsWith(DESCRIPTION, "great"), lessThan(Car_ID, 4)); //获取查询结果 ResultSet<Car> result=cars.retrieve(query1); if(result.isNotEmpty()){ result.forEach(e->{ sbBuffer.append(e.toString()); sbBuffer.append("/n"); }); return sbBuffer.toString(); }else{ return "nothing found"; } }启动类:
@SpringBootapplication@RestControllerpublic class DemoApplication { @Autowired private searchService ss; public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @RequestMapping("/") public String hello(){ return ss.test1(); } }运行后访问8080端口,输出:找出了id小于4,且描述以greate开头的car.参考:
http://stackoverflow.com/questions/37766895/can-cqengine-query-an-object-inside-another-object
https://github.com/npgall/cqengine
https://dzone.com/articles/getting-started-cqengine-linq
新闻热点
疑难解答