├── 1 └── README.md ├── 2 └── README.md ├── 3 ├── 3.1.md ├── 3.2.md ├── 3.3.md ├── 3.3 │ └── 3.3.1.md ├── 3.4.md └── README.md ├── 4 ├── 4.1.md ├── 4.2.md ├── 4.3.md ├── 4.3 │ └── 4.3.1.md ├── 4.4.md ├── 4.4 │ ├── 4.4.1.md │ ├── 4.4.2.md │ ├── 4.4.3.md │ ├── 4.4.4.md │ ├── 4.4.5.md │ ├── 4.4.6.md │ └── 4.4.7.md ├── 4.5.md ├── 4.5 │ ├── 4.5.1.md │ ├── 4.5.2.md │ └── 4.5.3.md ├── 4.6.md ├── 4.6 │ ├── 4.6.1.md │ └── 4.6.2.md ├── 4.7.md ├── 4.7 │ ├── 4.7.1.md │ ├── 4.7.2.md │ └── 4.7.3.md └── README.md ├── 5 ├── 5.1.md ├── 5.1 │ ├── 5.1.1.md │ ├── 5.1.2.md │ └── 5.1.3.md ├── 5.2.md ├── 5.2 │ ├── 5.2.1.md │ ├── 5.2.2.md │ └── 5.2.3.md ├── 5.3.md ├── 5.3 │ ├── 5.3.1.md │ └── 5.3.2.md └── README.md ├── 6 ├── 6.1.md ├── 6.2.md ├── 6.3.md ├── 6.4.md └── README.md ├── Preface └── README.md ├── README.md ├── SUMMARY.md ├── _book ├── 1 │ └── README.md ├── 2 │ └── index.html ├── 3 │ ├── 3.1.md │ ├── 3.2.md │ ├── 3.3.md │ ├── 3.3 │ │ └── 3.3.1.md │ ├── 3.4.md │ └── index.html ├── 4 │ ├── 4.1.html │ ├── 4.2.html │ ├── 4.3.html │ ├── 4.3 │ │ └── 4.3.1.html │ ├── 4.4.html │ ├── 4.4 │ │ ├── 4.4.1.html │ │ ├── 4.4.2.html │ │ ├── 4.4.3.html │ │ ├── 4.4.4.html │ │ ├── 4.4.5.html │ │ ├── 4.4.6.html │ │ └── 4.4.7.html │ ├── 4.5.html │ ├── 4.5 │ │ ├── 4.5.1.html │ │ ├── 4.5.2.html │ │ └── 4.5.3.html │ ├── 4.6.html │ ├── 4.6 │ │ ├── 4.6.1.html │ │ └── 4.6.2.html │ ├── 4.7.html │ ├── 4.7 │ │ ├── 4.7.1.html │ │ ├── 4.7.2.html │ │ └── 4.7.3.md │ └── index.html ├── 5 │ ├── 5.1.html │ ├── 5.1 │ │ ├── 5.1.1.html │ │ ├── 5.1.2.html │ │ └── 5.1.3.html │ ├── 5.2.html │ ├── 5.2 │ │ ├── 5.2.1.html │ │ ├── 5.2.2.html │ │ └── 5.2.3.html │ ├── 5.3.html │ ├── 5.3 │ │ ├── 5.3.1.html │ │ └── 5.3.2.html │ └── index.html ├── 6 │ ├── 6.1.html │ ├── 6.2.html │ ├── 6.3.html │ ├── 6.4.html │ └── index.html ├── Preface │ └── index.html ├── gitbook │ ├── app.js │ ├── fonts │ │ └── fontawesome │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ ├── images │ │ ├── apple-touch-icon-precomposed-152.png │ │ └── favicon.ico │ ├── plugins │ │ ├── gitbook-plugin-disqus │ │ │ ├── plugin.css │ │ │ └── plugin.js │ │ ├── gitbook-plugin-fontsettings │ │ │ ├── buttons.js │ │ │ └── website.css │ │ ├── gitbook-plugin-highlight │ │ │ ├── ebook.css │ │ │ └── website.css │ │ ├── gitbook-plugin-livereload │ │ │ └── plugin.js │ │ ├── gitbook-plugin-search │ │ │ ├── lunr.min.js │ │ │ ├── search.css │ │ │ └── search.js │ │ └── gitbook-plugin-sharing │ │ │ └── buttons.js │ └── style.css ├── index.html └── search_index.json ├── book.json ├── cover.jpg └── node_modules └── gitbook-plugin-disqus ├── .npmignore ├── LICENSE ├── README.md ├── book ├── plugin.css └── plugin.js ├── index.js └── package.json /1/README.md: -------------------------------------------------------------------------------- 1 | # 1 项目元数据 2 | -------------------------------------------------------------------------------- /2/README.md: -------------------------------------------------------------------------------- 1 | # 项目元数据 2 | 3 | * Version Control - https://github.com/spring-projects/spring-data-elasticsearch 4 | 5 | * Bugtracker - https://jira.spring.io/browse/DATAES 6 | 7 | * Release repository - https://repo.spring.io/libs-release 8 | 9 | * Milestone repository - https://repo.spring.io/libs-milestone 10 | 11 | * Snapshot repository - https://repo.spring.io/libs-snapshot 12 | -------------------------------------------------------------------------------- /3/3.1.md: -------------------------------------------------------------------------------- 1 | # 3.1 核心概念 2 | -------------------------------------------------------------------------------- /3/3.2.md: -------------------------------------------------------------------------------- 1 | # 3.2 查询方法 2 | -------------------------------------------------------------------------------- /3/3.3.md: -------------------------------------------------------------------------------- 1 | # 3.3 repository接口定义 2 | -------------------------------------------------------------------------------- /3/3.3/3.3.1.md: -------------------------------------------------------------------------------- 1 | # 3.3.1 调整repository定义 2 | -------------------------------------------------------------------------------- /3/3.4.md: -------------------------------------------------------------------------------- 1 | # 3.4 定义查询方法 2 | -------------------------------------------------------------------------------- /3/README.md: -------------------------------------------------------------------------------- 1 | # 使用条件 2 | 3 | 需要使用Elasticsearch 0.20.2及以上的版本 -------------------------------------------------------------------------------- /4/4.1.md: -------------------------------------------------------------------------------- 1 | # 核心概念 2 | Spring Data repository抽象中最核心的接口就是*Repository*(显而易见的哈)。该接口使用了泛型,需要提供两个类型参数,第一个是接口处理的域对象类型,第二个是域对象的主键类型。这个接口常被看做是一个标记型接口,用来获取要操作的域对象类型和帮助开发者识别继承这个类的接口。在Repository的基础上,*CrudRepository*接口提供了针对实体类的复杂的CRUD(增删改查)操作。 3 | 4 | Example 1.CrudRepository interface(CrudRepository接口) 5 | ```java 6 | 7 | public interface CrudRepository 8 | extends Repository { 9 | 10 | S save(S entity); //1 11 | 12 | T findOne(ID primaryKey); //2 13 | 14 | Iterable findAll(); //3 15 | 16 | Long count(); //4 17 | 18 | void delete(T entity); //5 19 | 20 | boolean exists(ID primaryKey); //6 21 | 22 | // … more functionality omitted. 23 | } 24 | 25 | 1.保存实体类 26 | 2.返回指定id的实体类 27 | 3.返回所有实体类 28 | 4.返回实体类的数量 29 | 5.删除指定实体类 30 | 6.判断指定id的实体类是否存在 31 | 32 | ``` 33 | 34 | >Spring Data也提供了一些针对特定持久化技术的抽象,例如*JpaRepository*和*MongoRepository*。这些接口均继承了*CrudRepository* 35 | 36 | 37 | *PagingAndSortingRepository*接口在*CrudRepository*的基础上增加了一些方法,使开发者可以方便的对实体类进行分页和排序。 38 | 39 | Example 2.PagingAndSortingRepository 40 | ```java 41 | public interface PagingAndSortingRepository 42 | extends CrudRepository { 43 | 44 | Iterable findAll(Sort sort); 45 | 46 | Page findAll(Pageable pageable); 47 | } 48 | ``` 49 | 在分页长度为20的基础上,想要获取第二页的*User*数据,代码如下 50 | 51 | ```java 52 | PagingAndSortingRepository repository = // … get access to a bean 53 | Page users = repository.findAll(new PageRequest(1, 20)); 54 | ``` 55 | 除了查询方法,还可以使用在查询基础上衍生出的count(获取数量)和delete(删除)方法。 56 | 57 | Example 3.Derived Count Query(获取数量) 58 | ```java 59 | public interface UserRepository extends CrudRepository { 60 | 61 | Long countByLastname(String lastname); 62 | } 63 | ``` 64 | 65 | Example 3.Derived Delete Query(删除) 66 | ```java 67 | public interface UserRepository extends CrudRepository { 68 | 69 | Long deleteByLastname(String lastname); 70 | 71 | List removeByLastname(String lastname); 72 | 73 | } 74 | ``` 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /4/4.2.md: -------------------------------------------------------------------------------- 1 | # 查询方法 2 | 标准的CRUD(增删改查)功能都要使用查询语句来查询数据库。但通过使用Spring Data,只要四个步骤就可以实现。 3 | 4 | 1.声明一个继承Repository接口或其子接口的持久层接口。并标明要处理的域对象类型及其主键的类型(在下面的例子中,要处理的域对象是Person,其主键类型是Long) 5 | ```java 6 | interface PersonRepository extends Repository {...} 7 | ``` 8 | 9 | 2.在接口中声明查询方法(spring会为其生成实现代码) 10 | 11 | ```java 12 | interface PersonRepository extends Repository { 13 | List findByLastname(String lastname); 14 | } 15 | ``` 16 | 17 | 3.让Spring创建对这些接口的代理实例。 18 | 通过JavaConfig 19 | 20 | ```java 21 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 22 | 23 | @EnableJpaRepositories 24 | class Config {} 25 | ``` 26 | 通过XML配置 27 | ```xml 28 | 29 | 36 | 37 | 38 | 39 | 40 | ``` 41 | 这里使用JPA的命名空间作为例子,需要根据实际使用的模块更改命名空间,比如可以改为mongodb等等。需要注意的是,在使用JavaConfig时,如果需要自定义扫描的包而不是使用其默认值,可以利用注解@EnableJpaRepositories的basePackage属性。具体使用方式如下: 42 | 43 | ```java 44 | @EnableJpaRepositories(basePackages = "com.cshtong")//单个包 45 | @EnableJpaRepositories(basePackages = {"com.cshtong.sample.repository", "com.cshtong.tower.repository"})//多个包路径 46 | 47 | ``` 48 | 49 | 50 | 4.注入repository实例,并使用 51 | ```java 52 | public class SomeClient { 53 | 54 | @Autowired 55 | private PersonRepository repository; 56 | 57 | public void doSomething() { 58 | List persons = repository.findByLastname("Matthews"); 59 | } 60 | } 61 | ``` 62 | 这一部分会在之后详细解释 -------------------------------------------------------------------------------- /4/4.3.md: -------------------------------------------------------------------------------- 1 | # repository接口定义 2 | 在第一步中我们定义了一个针对特定域对象的repository接口,接口继承了Repository接口并且标明了域对象类型及其主键类型。如果想要暴露CRUD方法可以不继承Repository接口,直接继承CrudRepository接口即可。 3 | 4 | -------------------------------------------------------------------------------- /4/4.3/4.3.1.md: -------------------------------------------------------------------------------- 1 | # 调整repository定义 2 | 通常情况下,我们的repository接口会继承Repository,CrudRepository或PagingAndSortingRepository接口。但是,如果不想通过extend关键字继承Spring Data的接口,还可以采用在自定义的repository接口上加注解的方式,两种方式是等价的。例子如下: 3 | ```java 4 | public interface UserDao extends Repository{...} 5 | 6 | @RepositoryDefinition(domainClass = Person, idClass = Long.class) 7 | public interface PersonRepository {...} 8 | 9 | ``` 10 | 此外,继承CrudRepository接口,会为操作域对象提供了一组可立即使用的方法。如果开发者不想暴露CrudRepository接口的全部方法,只需简单的将需要的方法复制到自己的repository接口中。 11 | 12 | >这让我们可以在Spring Datade Repository的基础上定义自己的抽象接口 13 | 14 | Example 5.Selectively exposing CRUD methods(选择性暴露方法) 15 | ```java 16 | @NoRepositoryBean 17 | interface MyBaseRepository extends Repository { 18 | 19 | T findOne(ID id); 20 | 21 | T save(T entity); 22 | } 23 | 24 | interface UserRepository extends MyBaseRepository { 25 | 26 | User findByEmailAddress(EmailAddress emailAddress); 27 | } 28 | 29 | ``` 30 | 在上面的代码中,我们先定义了一个公共的基础接口MyBaseRepository,并提供findOne和save两个方法。接着声明一个UserRepository的接口并继承基础接口MyBaseRepository,所以UserRepository拥有保存User,根据id查找user和根据邮箱地址查找User三个方法。 31 | >注意,中间过渡的接口MyBaseRepository上加了NoRepositoryBean注解,这个注解是告诉Spring Data不要为这个接口创建repository代理实例。 32 | -------------------------------------------------------------------------------- /4/4.4.md: -------------------------------------------------------------------------------- 1 | # 定义查询方法 2 | 通过方法名,Spring Data有两种方式获得开发者的查询意图。一是直接解析方法名,二是使用@Query创建的查询。那么到底使用哪种方式呢?Spring Data有一套策略来决定创建的查询。 3 | -------------------------------------------------------------------------------- /4/4.4/4.4.1.md: -------------------------------------------------------------------------------- 1 | # 查询策略 2 | Spring Data repository使用下面的一套策略来决定最后创建的查询。可以通过配置XML中的*query-loop-strategy*属性或Javaconfig中Enable${store}Repositories注解的*queryLookupStrategy*属性来调整策略。某些特定的数据存储可能不支持所有策略。 3 | 4 | * *CREATE* 通过解析方法名构建查询,会删除方法名的某些前缀(eg:findBy),并解析剩下的部分,会在下一节[创建查询](./4.4.2.md)中详细讲。 5 | * *USE_DECLARED_QUERY* 如果方法通过 @Query 指定了查询语句,则使用该语句创建Query;如果没有,则查找是否定义了符合条件的Named Query,如果找到,则使用该命名查询;如果两者都没有找到,则抛出异常。使用@Query声明查询语句的例子如下: 6 | 7 | ```java 8 | //使用Query注解 9 | @Query("select a from AccountInfo a where a.accountId = ?1") 10 | public AccountInfo findByAccountId(Long accountId); 11 | 12 | ``` 13 | * *CREATE_IF_NOT_FOUND(默认)* 结合了*CREATE*和*USE_DECLARED_QUERY* 两种策略,会先尝试查找声明好的查询,如果没有找到,就按照解析方法名的方式构建查询。这是默认的查询策略,如果不更改配置,会一直使用这种策略构建查询。这种策略支持通过方法名快速定义一个查询,也允许引入声明好的查询。 14 | -------------------------------------------------------------------------------- /4/4.4/4.4.2.md: -------------------------------------------------------------------------------- 1 | # 创建查询 2 | Spring Data repository自带了一个非常有用的查询构造器。它会从方法名中去掉类似*find..By*,*read...By*,*query...By*,*count...By*之类的前缀,然后解析剩余的名字。我们也可以在方法名中加入更多的表达式,比如查询时需要distinct约束,那么在方法名中加入Distinct即可。方法名中的第一个By是一个分解符,代表着查询语句的开始,我们可以用And或Or来将多个查询条件关联起来。 3 | 4 | Example 6.Query creation from method names(通过方法名创建查询) 5 | 6 | ```java 7 | public interface PersonRepository extends Repository { 8 | 9 | List findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); 10 | 11 | // Enables the distinct flag for the query 12 | // 在查询中使用distinct约束 13 | List findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); 14 | List findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); 15 | 16 | // Enabling ignoring case for an individual property 17 | // 忽略大小写 在方法名中加入IgnoreCase 18 | List findByLastnameIgnoreCase(String lastname); 19 | // Enabling ignoring case for all suitable properties 20 | // 所有属性都忽略大小写 在方法名中加入AllIgnoreCase 21 | List findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); 22 | 23 | // Enabling static ORDER BY for a query 24 | // 排序 在方法名中加入OrderBy 25 | List findByLastnameOrderByFirstnameAsc(String lastname); 26 | List findByLastnameOrderByFirstnameDesc(String lastname); 27 | } 28 | 29 | ``` 30 | 对方法名的解析结果取决于实际要操作的数据库/搜索引擎是什么。另外,还有一些普遍的问题要注意: 31 | 32 | * 在方法名中,可以使用*And*和*Or*连接多个属性。除此之外还可以使用*Between*,*LessThan*,*GreaterThan*,*Like*等等,不同数据库支持的连接符是不一样的,需要查看相关文档 33 | * 可以使用IgnoreCase来忽略单个属性的大小写,比如*findByLastnameIgoreCase*,也可以使用*AllIgnoreCase*来忽略全部属性的大小写。前提是,实际选择的数据库/搜索引擎支持。 34 | * 可以使用*OrderBy*来对相关属性进行排序。具体是升序还是降序,是通过*Asc*和*Desc*控制的。如果想了解动态排序,请看[处理特殊参数](./4.4.4.md)。 35 | -------------------------------------------------------------------------------- /4/4.4/4.4.3.md: -------------------------------------------------------------------------------- 1 | # 属性表达式 2 | 接下来我们来看看属性表达式。在之前的例子中,属性表达式只涉及到被管理的实体类的直接属性,在创建查询时我们已经确保解析出的属性是被管理实体类的属性之一。实际上,我们可以定义嵌套属性。假设Person类有一个Address,Address中又有ZipCode。在这种情况下,下面方法的方法名会通过x.address.zipCode来检索属性。 3 | 4 | ```java 5 | List findByAddressZipCode(ZipCode zipCode); 6 | ``` 7 | Spring Data的查询构造器会先把*AddressZipCode*当做一个整体,检查其是不是实体类的一个属性。如果是,就使用这个属性。如果不是,会按照驼峰式从右向左进行分割,再进行属性匹配。在上面的例子中,会将*AddressZipCode*分为*AddressZip*和*Code*。如果第一次分割之后还没有找到相匹配的属性,构造器会左移分割点重新进行分割,分为*Address*和*ZipCode*,并继续解析是否有相匹配的属性。 8 | 在大多数情况下,构造器都能够正确的解析出相匹配的属性。但在某些特殊情况下,可能会选择了错误的属性。假设*Person*类中除了*address*外,还有一个*addressZip*属性。那么构造器会在第一次分割后就匹配到相应的属性,然后报错(因为*addressZip*中没有*code*属性)。 9 | 为了避免的解析的歧义问题,我们可以在方法名中使用'_'符号来显式的表达意图,更改后的方法名如下: 10 | ```java 11 | List findByAddress_ZipCode(ZipCode zipCode); 12 | ``` 13 | 因为构造器已经将下划线作为保留字符,所以强烈建议开发者遵循标准的Java命名规范,不要在属性名中使用下划线,采用驼峰式命名。 14 | 15 | -------------------------------------------------------------------------------- /4/4.4/4.4.4.md: -------------------------------------------------------------------------------- 1 | # 处理特殊参数 2 | 通过上面的例子,我们知道可以方便的通过定义方法的参数来处理查询中的参数。除此之外,我们还可以为方法添加某些特定类型的参数(如:*Pageable*和*Sort*)来动态的在查询中添加分页和排序。 3 | 4 | Example 7. Using Pageable, Slice and Sort in query methods(查询中进行分页和排序) 5 | 6 | ```java 7 | Page findByLastname(String lastname, Pageable pageable); 8 | 9 | Slice findByLastname(String lastname, Pageable pageable); 10 | 11 | List findByLastname(String lastname, Sort sort); 12 | 13 | List findByLastname(String lastname, Pageable pageable); 14 | ``` 15 | 第一个例子中我们向方法传递一个*org.springframework.data.domain.Pageable*的实例来为查询动态的添加分页,返回的*Page*对象中包含元素总数和当前页的数据。其中的元素总数是通过Spring Data自动触发的一个count查询获得的。但是count查询有时会降低一定的性能,所以在不需要总数时,我们可以使用*Slice*来代替*Page*。Slice仅仅可以知道是否有可用的下一个Slice。 16 | 排序操作也可以通过Pageable实例来处理。但如果你需要的只是排序,只需要为方法添加*org.springframework.data.domain.Sort*类型的参数即可。我们也可以只简单的返回一个list,这时就不会执行count查询,只查询给定范围的实体类。 17 | 18 | >如果想知道总共有多少页,就必须触发一个额外的count查询 -------------------------------------------------------------------------------- /4/4.4/4.4.5.md: -------------------------------------------------------------------------------- 1 | # 限定查询结果集大小 2 | Spring Data允许开发者使用*first*和*top*关键字对返回的查询结果集大小进行限定。fisrt和top需要跟着一个代表返回的结果集的最大大小的数字。如果没有跟着一个数字,那么返回的结果集大小默认为1。 3 | 4 | Example 8.Limiting the result size of query with Top and First(利用first和top限制返回的结果集大小) 5 | ```java 6 | User findFirstByOrderByLastnameAsc(); 7 | 8 | User findTopByOrderByAgeDesc(); 9 | 10 | Page queryFirst10ByLastname(String lastname, Pageable pageable); 11 | 12 | Slice findTop3ByLastname(String lastname, Pageable pageable); 13 | 14 | List findFirst10ByLastname(String lastname, Sort sort); 15 | 16 | List findTop10ByLastname(String lastname, Pageable pageable); 17 | 18 | ``` 19 | 20 | 限制结果集的表达式还支持*Distinct*关键字。并且,当返回的结果集大小限制为1时,Spring Data支持将返回结果包装到Optional(java 8新增,这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象)之中,例子如下: 21 | ```java 22 | Optional findFirstByOrderByLastnameAsc(); 23 | 24 | ``` 25 | 在查询用page和slice来进行分页查询的情况下,同样可以使用*first*和*top*来对结果集大小进行限制。 26 | 27 | >注意,如果在使用*Sort*参数对查询结果进行排序的基础上加上对结果集大小的限制,就可以轻易的获得最大的K个元素或最小的K个元素。 28 | -------------------------------------------------------------------------------- /4/4.4/4.4.6.md: -------------------------------------------------------------------------------- 1 | # 利用Stream(流)处理查询结果 2 | 3 | 我们可以使用Stream作为返回类型可以对查询结果进行逐个处理。 4 | 5 | Example 9. Stream the result of a query with Java 8 Stream(stream查询结果) 6 | ```java 7 | @Query("select u from User u") 8 | Stream findAllByCustomQueryAndStream(); 9 | 10 | Stream readAllByFirstnameNotNull(); 11 | 12 | @Query("select u from User u") 13 | Stream streamAllPaged(Pageable pageable); 14 | ``` 15 | 16 | >一个Stream中可能包含底层数据存储的特定资源,所以在使用后必须关闭。可以通过调用close()方法,也可以使用java 7中的try-with-resources块 17 | 18 | Example 10. Working with a Stream result in a try-with-resources block(在块中使用Stream) 19 | ```java 20 | try (Stream stream = repository.findAllByCustomQueryAndStream()) { 21 | stream.forEach(…); 22 | } 23 | ``` 24 | > 目前,不是所有的Spring Data模块都支持将Stream作为返回类型 25 | -------------------------------------------------------------------------------- /4/4.4/4.4.7.md: -------------------------------------------------------------------------------- 1 | # 异步处理查询结果 2 | Spring Data repository中的查询可以异步执行,参考[Spring执行异步方法](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/)。这意味着方法可以在被调用时立刻返回,而真正的查询执行会被当做一个任务提交到Spring的TaskExecutor。 3 | 4 | ```java 5 | @Async 6 | Future findByFirstname(String firstname); //1 7 | 8 | @Async 9 | CompletableFuture findOneByFirstname(String firstname); //2 10 | 11 | @Async 12 | ListenableFuture findOneByLastname(String lastname); //3 13 | 14 | 1.使用java.util.concurrent.Future作为返回类型。 15 | 2.使用Java 8中的java.util.concurrent.CompletableFuture作为返回类型。 16 | 3.使用org.springframework.util.concurrent.ListenableFuture作为返回类型 17 | 18 | ``` 19 | -------------------------------------------------------------------------------- /4/4.5.md: -------------------------------------------------------------------------------- 1 | # 创建repository实例 2 | 这一部分将介绍如何为定义好的repository接口创建实例和bean。一种方式是使用Spring Data模块下支持repository配置的Spring命名空间。不过,通常推荐使用JavaConfig风格的配置。 3 | -------------------------------------------------------------------------------- /4/4.5/4.5.1.md: -------------------------------------------------------------------------------- 1 | # XML配置 2 | 每个Spring Data模块都包含一个repository元素,通过这个元素开发者可以轻松的定义spring扫描包的路径。 3 | 4 | Example 11.Enabling Spring Data repositories via XML 5 | 6 | ```xml 7 | 8 | 15 | 16 | 17 | 18 | 19 | ``` 20 | 在上面的例子中,Spring扫描base-package中指定的路径及其包含的所有包,检测出继承Repository或者其子接口的接口。每找到一个接口,FactoryBean会创建对应的代理去处理查询方法的调用。每个注册的bean的名称都来自于接口名称,例如:UserRepository将会被注册为userRepository。base-package允许使用通配符来定义扫描路径。 21 | 22 | ### 使用过滤器 23 | 24 | 默认情况下,Spring会找到配置路径下的所有接口并为其创建一个bean实例。但有些情况下开发者可能想要更细致的控制创建bean实例的接口。这时候,可以在元素中使用。这些元素的详细用法可以参考[spring参考文档](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-scanning-filters)。 25 | 下面的配置就是排除某些特定接口的例子: 26 | 27 | Example 12. Using exclude-filter element(使用exclude-filter元素) 28 | ```xml 29 | 30 | 31 | 32 | ``` 33 | 上面的配置排除了所有以SomeRepository结尾的接口。 34 | -------------------------------------------------------------------------------- /4/4.5/4.5.2.md: -------------------------------------------------------------------------------- 1 | # JavaConfig 2 | 我们也可以使用JavaConfig类中的注解@Enable${store}Repositories来配置扫描包的路径。在实际开发中,要针对不同的持久化存储替换不同的${store}。下面是使用JavaConfig配置的一个例子: 3 | Example 13. Sample annotation based repository configuration 4 | ```java 5 | @Configuration 6 | @EnableJpaRepositories("com.acme.repositories") 7 | class ApplicationConfiguration { 8 | 9 | @Bean 10 | public EntityManagerFactory entityManagerFactory() { 11 | //... 12 | } 13 | } 14 | ``` 15 | >在上面的例子中使用了针对Jpa的注解,需要根据实际使用的存储修改。同样地,使用的存储不同,定义的*EntityManagerFactory*bean也不同。具体请查看针对指定存储配置的文档。 16 | -------------------------------------------------------------------------------- /4/4.5/4.5.3.md: -------------------------------------------------------------------------------- 1 | # 独立使用 2 | 开发者可以在脱离Spring容器的情况下利用RepositoryFactory来使用Spring Data repository(比如在CDI环境下),但仍然需要将某些Spring的依赖包加到classpath中。 3 | 4 | Example 14. Standalone usage of repository factory(独立使用) 5 | 6 | ```java 7 | RepositoryFactorySupport factory = … // Instantiate factory here(初始化factory) 8 | UserRepository repository = factory.getRepository(UserRepository.class); 9 | ``` 10 | -------------------------------------------------------------------------------- /4/4.6.md: -------------------------------------------------------------------------------- 1 | # 自定义repository实现 2 | 在开发过程中,常常需要为一些repository方法添加自定义的实现。Spring Data repository允许开发者自定义repository方法。 3 | -------------------------------------------------------------------------------- /4/4.6/4.6.1.md: -------------------------------------------------------------------------------- 1 | # 为单一的repositories添加自定义方法 2 | 3 | 为了通过自定义方法来丰富repository,首先要定义一个接口和一个接口的实现类。 4 | 5 | Example 15. Interface for custom repository functionality(自定义接口) 6 | 7 | ```java 8 | interface UserRepositoryCustom { 9 | public void someCustomMethod(User user); 10 | } 11 | ``` 12 | Example 16. Implementation of custom repository functionality(接口的实现类) 13 | 14 | ```java 15 | class UserRepositoryImpl implements UserRepositoryCustom { 16 | 17 | public void someCustomMethod(User user) { 18 | // Your custom implementation 19 | } 20 | } 21 | ``` 22 | >接口的实现类名字后缀必须为*impl*才能在扫描包时被找到。 23 | 24 | 实现类本身并不依赖于Spring Data,就是一个普通的Srping的bean,所以可以是用标准的依赖注入在其中注入其它相关的bean,比如JdbcTemplate等等。 25 | 26 | Example 17. Changes to the your basic repository interface(修改基础的repository接口) 27 | 28 | ```java 29 | interface UserRepository extends CrudRepository, UserRepositoryCustom { 30 | 31 | // Declare query methods here 32 | } 33 | ``` 34 | 上面代码在让标准的repository接口继承了自定义的接口,将标准的CRUD和自定义的方法结合到了一起。 35 | 36 | ### 配置 37 | 在使用Xml配置时,Spring框架会自动检测指定包路径下的实现类。实现类的后缀必须满足属性*repository-impl-postfix*的定义,默认后缀是*Impl*。 38 | 39 | ```xml 40 | 41 | 42 | 43 | ``` 44 | 在第一个配置中,spring会找到类*com.acme.repository.UserRepositoryImpl*,而在第二个配置中,spring会尝试查找*com.acme.repository.UserRepositoryFooBar*类 45 | 46 | ### 人工装载 47 | 上面的例子使用了基于注解的配置来自动装载。如果自定义的实现类需要特殊的装载,也可以手动的声明一个bean,名字要遵循上一节定义的命名规范。 48 | 49 | Example 19. Manual wiring of custom implementations(人工装载自定义的实现类) 50 | ```xml 51 | 52 | 9 | extends PagingAndSortingRepository { 10 | 11 | void sharedCustomMethod(ID id); 12 | } 13 | ``` 14 | 现在,开发者的其他repository接口需要继承定义的中间接口而不是继承*Repository*接口。接下来需要为这个中间接口创建实现类。这个实现类是基于Repository中的基类的(不同的持久化存储继承的基类也不相同,这里以Jpa为例),这个类会被当做repository代理的自定义类来执行。 15 | Example 21. Custom repository base class(自定义reposotory基类) 16 | ```java 17 | public class MyRepositoryImpl 18 | extends SimpleJpaRepository implements MyRepository { 19 | 20 | private final EntityManager entityManager; 21 | 22 | public MyRepositoryImpl(JpaEntityInformation entityInformation,EntityManager entityManager) { 23 | super(entityInformation, entityManager); 24 | 25 | // Keep the EntityManager around to used from the newly introduced methods. 26 | this.entityManager = entityManager; 27 | } 28 | 29 | public void sharedCustomMethod(ID id) { 30 | // implementation goes here 31 | } 32 | } 33 | ``` 34 | Spring中命名空间默认会为base-package下所有的接口提供一个实例。但MyRepository只是作为一个中间接口,并不需要创建实例。所以我们可以使用@NoRepositoryBean注解或将其排除在base-package的配置中 35 | 36 | 最后一步是使用JavaConfig或Xml配置这个自定义的repository基类。 37 | 38 | Example 22. Configuring a custom repository base class using JavaConfig(使用JavaConfig配置repository基类) 39 | ```java 40 | @Configuration 41 | @EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class) 42 | class ApplicationConfiguration { … } 43 | ``` 44 | 也可使用Xml的方式配置。 45 | 46 | Example 23. Configuring a custom repository base class using XML(使用xml配置自定义repository基类) 47 | ```xml 48 | 50 | ``` 51 | -------------------------------------------------------------------------------- /4/4.7.md: -------------------------------------------------------------------------------- 1 | # 扩展Spring Data 2 | 这一章将介绍如何把Spring Data扩展到其他的框架中。接下来让我们看看如何将Spring Data整合到Spring MVC中。 3 | -------------------------------------------------------------------------------- /4/4.7/4.7.1.md: -------------------------------------------------------------------------------- 1 | # WEB支持 2 | Spring Data带有很多的web支持。要使用它们,需要在classpath中加入Spring MVC的jar包,有的还需要整合Spring HATEOAS。通常情况下,只需在JavaConfig的配置类中使用*@EnableSpringDataWebSupport*注解即可。 3 | 4 | Example 24. Enabling Spring Data web support(使用Spring Data的web支持) 5 | ```java 6 | @Configuration 7 | @EnableWebMvc 8 | @EnableSpringDataWebSupport 9 | class WebConfiguration { } 10 | ``` 11 | *@EnableSpringDataWebSupport*注解会注册一些组件,我们会在之后讨论。它同样也会去检测classpath中的Spring HATEOAS,并且注册他们。 12 | 13 | 如果不想通过JavaConfig开启web支持,也可以使用xml配置,将*SpringDataWebSupport*和*HateoasAwareSpringDataWebSupport*注册为Spring的bean。 14 | 15 | Example 25. Enabling Spring Data web support in XML(使用xml配置) 16 | ```xml 17 | 18 | 19 | 20 | 21 | ``` 22 | #### 基础的web支持 23 | 上面的配置会注册一些基础组件: 24 | 25 | * *DomainClassConverter*:使Spring MVC可以从请求参数或路径变量中解析repository管理的域对象的实例。 26 | * *HandlerMethodArgumentResolver*:使Spring mvc能从请求参数来解析Pageable和Sort实例 27 | 28 | ##### DomainClassConverter 29 | 30 | *DomainClassConverter* 允许开发者在SpringMVC控制层的方法中直接使用域对象类型(Domain types),而无需通过repository手动查找这个实例。 31 | 32 | Example 26. A Spring MVC controller using domain types in method signatures (在Spring MVC控制层方法中直接使用域对象类型) 33 | 34 | ```java 35 | @Controller 36 | @RequestMapping("/users") 37 | public class UserController { 38 | 39 | @RequestMapping("/{id}") 40 | public String showUserForm(@PathVariable("id") User user, Model model) { 41 | 42 | model.addAttribute("user", user); 43 | return "userForm"; 44 | } 45 | } 46 | ``` 47 | 上面的方法直接接收了一个User对象,开发者不需要做任何的搜索操作,转换器会自动将路径变量id转为User对象的id,并且调用了findOne()方法查询出User实体。 48 | 49 | >注意:当前的Repository 必须实现CrudRepository 50 | 51 | ##### HandlerMethodArgumentResolver 52 | 这个配置同时注册了*PageableHandlerMethodArgumentResolver*和*SortHandlerMethodArgumentResolver*,是开发者可以在controller的方法中使用*Pageable*和*Sort*作为参数。 53 | Example 27. Using Pageable as controller method argument(在controller中使用Pageable作为参数) 54 | ```java 55 | @Controller 56 | @RequestMapping("/users") 57 | public class UserController { 58 | 59 | @Autowired UserRepository repository; 60 | 61 | @RequestMapping 62 | public String showUsers(Model model, Pageable pageable) { 63 | 64 | model.addAttribute("users", repository.findAll(pageable)); 65 | return "users"; 66 | } 67 | } 68 | ``` 69 | 通过上面的方法定义,Spring MVC会使用下面的默认配置尝试从请求参数中得到一个Pageable的实例。 70 | Table 1. Request parameters evaluated for Pageable instances 71 | page(由于构造Pageable实例的请求参数) 72 | 73 | |参数名|作用| 74 | |:---|:---| 75 | |page|想要获取的页数,默认为0| 76 | |size|获取页的大小,默认为20| 77 | |sort|需要排序的属性,格式为*property,property(,ASC/DESC)*,默认升序排序。支持多个字段排序,比如*?sort=firstname&sort=lastname,asc* 78 | 79 | 如果开发者想要自定义分页或排序的行为,可以继承*SpringDataWebConfiguration*或*HATEOAS-enabled*,并重写*pageableResolver()*或*sortResolver()*方法,引入自定义的配置文件来代替使用@Enable-注解。 80 | 81 | 开发者也可以针对多个表定义多个*Pageable*或*Sort*实例,需要使用Spring的*@Qualifier*注解来区分它们。并且请求参数名要带有*${qualifier}_*的前缀。例子如下: 82 | 83 | ```java 84 | public String showUsers(Model model, 85 | @Qualifier("foo") Pageable first, 86 | @Qualifier("bar") Pageable second) {...} 87 | ``` 88 | 请求中需要带有foo_page和bar_page等参数。 89 | 90 | 默认的*Pageable*相当于*new PageRequest(0, 20)*,但开发者可以在*Pageable*参数上使用*@PageableDefaults*来自定义。 91 | 92 | ##### 超媒体分页 93 | 94 | Spring HATEOAS有一个PagedResources类,它丰富了Page实体以及一些让用户更容易导航到资源的链接。Page转换到PagedResources是由一个实现了Spring HATEOAS ResourceAssembler接口的实现类:PagedResourcesAssembler提供转换的。 95 | Example 28. Using a PagedResourcesAssembler as controller method argument(使用PagedResourcesAssembler当做方法参数) 96 | 97 | ```java 98 | @Controller 99 | class PersonController { 100 | 101 | @Autowired PersonRepository repository; 102 | 103 | @RequestMapping(value = "/persons", method = RequestMethod.GET) 104 | HttpEntity> persons(Pageable pageable, 105 | PagedResourcesAssembler assembler) { 106 | 107 | Page persons = repository.findAll(pageable); 108 | return new ResponseEntity<>(assembler.toResources(persons), HttpStatus.OK); 109 | } 110 | } 111 | ``` 112 | 上面的toResources方法会执行以下的几个步骤: 113 | * Page对象的content会转换成为PagedResources对象的content。 * PagedResources会的到一个PageMetadata的实体,包含从Page跟PageRequest得到的信息。 * PagedResources会根据状态得到prev跟next链接,这些链接指向URI所匹配的方法。分页参数会根据PageableHandlerMethodArgumentResolver配置,以让其能够在后面的方法中解析使用。 114 | 假设我们数据库中存有30个人。发送一个GET请求*http://localhost:8080/persons*,得到的返回结果如下: 115 | ```json { "links" : [ { "rel" : "next", 116 | "href" : "http://localhost:8080/persons?page=1&size=20 } 117 | ], 118 | "content" : [ 119 | … // 20 Person instances rendered here 120 | ], 121 | "pageMetadata" : { 122 | "size" : 20, 123 | "totalElements" : 30, 124 | "totalPages" : 2, 125 | "number" : 0 126 | } 127 | } ``` 128 | 129 | 从返回结果中可以看出assembler生成了正确的URI,并根据默认配置设置了分页的请求参数。这意味着,如果我们更改了配置,这个链接会自动更改。默认情况下,assembler生成的链接会指向被调用的controller方法,但也可以通过重写*PageResourceAssembler.toResource{...}*方法提供一个自定义的链接。 130 | 131 | ##### QueryDSL web支持 132 | 对于那些集成了[QueryDSL](http://www.querydsl.com/)的存储可以从请求的查询参数中直接获得查询语句。 133 | 这意味着下面的针对*User*的请求参数: 134 | ``` 135 | ?firstname=Dave&lastname=Matthews 136 | ``` 137 | 会通过*QuerydslPredicateArgumentResolver*解析成: 138 | ```java 139 | QUser.user.firstname.eq("Dave").and(QUser.user.lastname.eq("Matthews")) 140 | ``` 141 | >如果使用了@EnableSpringDataWebSupport注解,并且classpath中包含Querydsl,那么该功能会自动开启。 142 | 143 | 在方法中加入*@QuerydslPredicate*注解,可以提供我们使用*Predicate* 144 | 145 | ```java 146 | @Controller 147 | class UserController { 148 | 149 | @Autowired UserRepository repository; 150 | 151 | @RequestMapping(value = "/", method = RequestMethod.GET) 152 | String index(Model model, @QuerydslPredicate(root = User.class) Predicate predicate, //1 153 | Pageable pageable, @RequestParam MultiValueMap parameters) { 154 | 155 | model.addAttribute("users", repository.findAll(predicate, pageable)); 156 | 157 | return "index"; 158 | } 159 | } 160 | 1.解析查询参数来匹配针对user的Predicate 161 | ``` 162 | 默认的绑定如下: 163 | 164 | * 一个对象对应一个简单属性相当于*eq* 165 | ``` 166 | ?firstname=2 167 | ``` 168 | * 多个属性上对应一个对象相当于*contains* 169 | ``` 170 | ?firstname=2&firstname=3 171 | ``` 172 | * 简单属性对应一个集合相当于*in* 173 | ``` 174 | ?firstname=[2,3,4,5] 175 | ``` 176 | 177 | 这些绑定规则可以通过*@QuerydslPredicate*的*bindings*属性或者使用Java 8新引入的*default*方法在repository接口中加入*QuerydslBinderCustomizer*方法来更改。 178 | ```java 179 | interface UserRepository extends CrudRepository, 180 | QueryDslPredicateExecutor, //1 181 | QuerydslBinderCustomizer { //2 182 | 183 | @Override 184 | default public void customize(QuerydslBindings bindings, QUser user) { 185 | 186 | bindings.bind(user.username).first((path, value) -> path.contains(value)) //3 187 | bindings.bind(String.class) 188 | .first((StringPath path, String value) -> path.containsIgnoreCase(value)); //4 189 | bindings.excluding(user.password); //5 190 | } 191 | } 192 | 193 | 1.QueryDslPredicateExecutor provides access to specific finder methods for Predicate. 194 | 2.QuerydslBinderCustomizer defined on the repository interface will be automatically picked up and shortcuts @QuerydslPredicate(bindings=…​). 195 | 3.Define the binding for the username property to be a simple contains binding. 196 | 4.Define the default binding for String properties to be a case insensitive contains match. 197 | 5.Exclude the password property from Predicate resolution. 198 | ``` 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /4/4.7/4.7.2.md: -------------------------------------------------------------------------------- 1 | # Repository填充 2 | 如果使用过Spring提供的JDBC模块,可能会对使用SQL脚本填充*DataSource*。Spring Data中也提供了相似的功能来填充repository,只不过不是使用SQL,而是使用XML或JSON来定义数据, 3 | 4 | 假设有一个*data.json*文件,内容如下: 5 | 6 | Example 29. Data defined in JSON(使用JSON定义数据) 7 | ```json 8 | [ { "_class" : "com.acme.Person", 9 | "firstname" : "Dave", 10 | "lastname" : "Matthews" }, 11 | { "_class" : "com.acme.Person", 12 | "firstname" : "Carter", 13 | "lastname" : "Beauford" } ] 14 | ``` 15 | 为了把前面定义的数据填充到PersonRepository中可以使用repository命名空间提供的popilator元素。 16 | Example 30. Declaring a Jackson repository populator(声明Jackson repository populator) 17 | ```xml 18 | 19 | 26 | 27 | 28 | 29 | 30 | ``` 31 | 上面的配置会让*data.json*文件可以在其他地方通过Jackson的Object Mapper读取和反序列化。 32 | 33 | JSON object的类型可以通过解析json文件中的*_class*属性得到。Spring框架会根据反序列化的对象选择合适的repository来处理。 34 | 35 | 如果想要用XML来定义repositries填充的数据,需要使用unmarshaller-populator元素,可以利用Spring OXM提供的组件,想要详细了解请参考[Spring参考文档](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/oxm.html): 36 | 37 | Example 31. Declaring an unmarshalling repository populator (using JAXB) 38 | ```xml 39 | 40 | 50 | 51 | 53 | 54 | 55 | 56 | 57 | ``` -------------------------------------------------------------------------------- /4/4.7/4.7.3.md: -------------------------------------------------------------------------------- 1 | # 保留网络支持 2 | -------------------------------------------------------------------------------- /4/README.md: -------------------------------------------------------------------------------- 1 | # 玩转Spring Data Repositories 2 | 抽象出Spring Data repository是因为在开发过程中,常常会为了实现不同持久化存储的数据访问层而写大量的大同小异的代码。Spring Data repository的目的就是要大幅减少这些重复的代码。 3 | 4 | >本章阐述了Spring Data repository的核心概念及接口。本章的内容来自Spring data的公共模块,配置和样例代码来自Java Persistence Api(JPA)模块。如有需要,可以将XML文件的命名空间调整到你所使用的特定模块(eg:elasticsearch/mongo 等等)。[命名空间参考文档](../6/6.1.md)涵盖了所有支持Repository API的Spring Data模块的XML配置。[Repository查询关键字说明文档](../6/6.3.md)内列出了repository支持的查询方法的关键字。如果想要了解其他特定模块的详细信息,可以查询指定模块的参考文档。 -------------------------------------------------------------------------------- /5/5.1.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | -------------------------------------------------------------------------------- /5/5.1/5.1.1.md: -------------------------------------------------------------------------------- 1 | # Spring命名空间 2 | Spring Data Elasticsearch模块包含一个自定义的命名空间,它允许我们定义repository bean和初始化一个*ElasticsearchServer*。 3 | 4 | 下面,我们像[创建Repository实例](http://)中描述的那样使用*repositories*元素查找Spring Data repository。 5 | 6 | Example 32. Setting up Elasticsearch repositories using Namespace(使用命名空间创建Elasticsearch repositories) 7 | 8 | ```xml 9 | 10 | 17 | 18 | 19 | 20 | 21 | ``` 22 | 使用*Transport Client*和*Node Client*元素注册一个*Elasticsearch Server*实例。 23 | 24 | Example 33. Transport Client using Namespace(使用Transport Client) 25 | 26 | ```xml 27 | 28 | 35 | 36 | 37 | 38 | 39 | ``` 40 | 41 | Example 34. Node Client using Namespace(使用Node Client) 42 | 43 | ```xml 44 | 45 | 52 | 53 | 54 | 55 | 56 | ``` 57 | -------------------------------------------------------------------------------- /5/5.1/5.1.2.md: -------------------------------------------------------------------------------- 1 | # 基于注解的配置 2 | Spring Data Elasticsearch repository可以通过XML配置,也可以通过JavaConfig的注解配置。 3 | 4 | Example 35. Spring Data Elasticsearch repositories using JavaConfig(使用JavaConfig) 5 | 6 | ```java 7 | @Configuration 8 | @EnableElasticsearchRepositories(basePackages = "org/springframework/data/elasticsearch/repositories") 9 | static class Config { 10 | 11 | @Bean 12 | public ElasticsearchOperations elasticsearchTemplate() { 13 | return new ElasticsearchTemplate(nodeBuilder().local(true).node().client()); 14 | } 15 | } 16 | ``` 17 | 上面的配置使用*ElasticsearchTemplate*创建了一个*Embedded Elasticsearch Server*。通过*@EnableElasticsearchRepositories*注解来启动Spring Data Elasticsearch Repositories,如果没有显式指定扫描的包路径,会扫描配置类所在的包。 18 | 19 | 20 | -------------------------------------------------------------------------------- /5/5.1/5.1.3.md: -------------------------------------------------------------------------------- 1 | # 使用CDI 2 | 3 | Spring Data Elasticsearch repositories也可以使用CDI注入。 4 | 5 | Example 36. Spring Data Elasticsearch repositories using JavaConfig(使用JavaConfig) 6 | 7 | ```java 8 | class ElasticsearchTemplateProducer { 9 | 10 | @Produces 11 | @ApplicationScoped 12 | public ElasticsearchOperations createElasticsearchTemplate() { 13 | return new ElasticsearchTemplate(nodeBuilder().local(true).node().client()); 14 | } 15 | } 16 | 17 | class ProductService { 18 | 19 | private ProductRepository repository; 20 | 21 | public Page findAvailableBookByName(String name, Pageable pageable) { 22 | return repository.findByAvailableTrueAndNameStartingWith(name, pageable); 23 | } 24 | 25 | @Inject 26 | public void setRepository(ProductRepository repository) { 27 | this.repository = repository; 28 | } 29 | } 30 | 31 | ``` 32 | -------------------------------------------------------------------------------- /5/5.2.md: -------------------------------------------------------------------------------- 1 | # 查询方法 2 | -------------------------------------------------------------------------------- /5/5.2/5.2.1.md: -------------------------------------------------------------------------------- 1 | # 查询策略 2 | Elasticsearch模块支持所有基本查询构建,比如String,Abstract,Criteria或通过方法名获得构建查询。 3 | 4 | ### 声明查询 5 | 通过解析方法名来构建查询有时可能满足不了开发者的需求,或造成方法名可读性差。这时可以使用*@Query*注解来声明一个查询(参考[使用@Query注解](./5.2.3.md)) 6 | -------------------------------------------------------------------------------- /5/5.2/5.2.2.md: -------------------------------------------------------------------------------- 1 | # 创建查询 2 | 通常情况下,Elasticsearch模块创建查询的机制与4.2节[查询方法](../../4/4.2.md)中描述的一样。通过下面的例子,我们来看看Elasticsearch模块会根据一个查询方法生成怎样的查询语句。 3 | 4 | Example 37. Query creation from method names(通过方法名创建查询) 5 | ```java 6 | public interface BookRepository extends Repository 7 | { 8 | List findByNameAndPrice(String name, Integer price); 9 | } 10 | ``` 11 | 根据上面的方法名会生成下面的Elasticsearch查询语句 12 | ```json 13 | { "bool" : 14 | { "must" : 15 | [ 16 | { "field" : {"name" : "?"} }, 17 | { "field" : {"price" : "?"} } 18 | ] 19 | } 20 | } 21 | ``` 22 | 下面的表格列出了所有Elasticsearch支持的关键字。 23 | 24 | Table 2. Supported keywords inside method names(方法名中支持的关键字) 25 | 26 | |关键字|例子|Elasticsearch查询语句| 27 | |:---|:---|:---| 28 | |And|findByNameAndPrice|{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} 29 | |Or|findByNameOrPrice|{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} 30 | |Is|findByName|{"bool" : {"must" : {"field" : {"name" : "?"}}}} 31 | |Not|findByNameNot|{"bool" : {"must_not" : {"field" : {"name" : "?"}}}} 32 | |LessThanEqual|findByPriceLessThan|{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} 33 | |GreaterThanEqual|findByPriceGreaterThan|{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} 34 | |Before|findByPriceBefore|{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} 35 | |After|findByPriceAfter|{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} 36 | |Like|findByNameLike|{"bool" : {"must" : {"field" : {"name" : {"query" : "?\*","analyze_wildcard" : true}}}}} 37 | |StartingWith|findByNameStartingWith|{"bool" : {"must" : {"field" : {"name" : {"query" : "?\*","analyze_wildcard" : true}}}}} 38 | |EndingWith|findByNameEndingWith|{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}} 39 | |Contains/Containing|findByNameContaining|{"bool" : {"must" : {"field" : {"name" : {"query" : "?","analyze_wildcard" : true}}}}} 40 | |In|findByNameIn(Collectionnames)|{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}} 41 | |NotIn|findByNameNotIn(Collectionnames)|{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}} 42 | |Near|findByStoreNear|暂不支持 43 | |True|findByAvailableTrue|{"bool" : {"must" : {"field" : {"available" : true}}}} 44 | |False|findByAvailableFalse|{"bool" : {"must" : {"field" : {"available" : false}}}} 45 | |OrderBy|findByAvailableTrueOrderByNameDesc|{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}} 46 | -------------------------------------------------------------------------------- /5/5.2/5.2.3.md: -------------------------------------------------------------------------------- 1 | # 使用@Query注解 2 | Example 38. Declare query at the method using the @Query annotation.(使用@Query注解声明查询) 3 | ```java 4 | public interface BookRepository extends ElasticsearchRepository { 5 | @Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}") 6 | Page findByName(String name,Pageable pageable); 7 | } 8 | ``` -------------------------------------------------------------------------------- /5/5.3.md: -------------------------------------------------------------------------------- 1 | # 其他Elasticsearch操作的支持 2 | 这一章会讲解无法通过repository接口直接使用的其他Elasticsearch操作。建议像[自定义repository实现](../4/4.6.md)这章中描述的那样为repository添加自定义的实现。 3 | -------------------------------------------------------------------------------- /5/5.3/5.3.1.md: -------------------------------------------------------------------------------- 1 | # 构建Filter 2 | 使用过滤器可以提高查询速度 3 | ```java 4 | private ElasticsearchTemplate elasticsearchTemplate; 5 | 6 | SearchQuery searchQuery = new NativeSearchQueryBuilder() 7 | .withQuery(matchAllQuery()) 8 | .withFilter(boolFilter().must(termFilter("id", documentId))) 9 | .build(); 10 | 11 | Page sampleEntities = 12 | elasticsearchTemplate.queryForPage(searchQuery,SampleEntity.class); 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /5/5.3/5.3.2.md: -------------------------------------------------------------------------------- 1 | # 利用Scan和Scroll处理大结果集 2 | 3 | Elasticsearch在处理大结果集时可以使用scan和scroll。在Spring Data Elasticsearch中,可以向下面那样使用*ElasticsearchTemplate*来使用scan和scroll处理大结果集。 4 | 5 | Example 39. Using Scan and Scroll(使用scan和scroll) 6 | ```java 7 | SearchQuery searchQuery = new NativeSearchQueryBuilder() 8 | .withQuery(matchAllQuery()) 9 | .withIndices("test-index") 10 | .withTypes("test-type") 11 | .withPageable(new PageRequest(0,1)) 12 | .build(); 13 | String scrollId = elasticsearchTemplate.scan(searchQuery,1000,false); 14 | List sampleEntities = new ArrayList(); 15 | boolean hasRecords = true; 16 | while (hasRecords){ 17 | Page page = elasticsearchTemplate.scroll(scrollId, 5000L , new ResultsMapper() 18 | { 19 | @Override 20 | public Page mapResults(SearchResponse response) { 21 | List chunk = new ArrayList(); 22 | for(SearchHit searchHit : response.getHits()){ 23 | if(response.getHits().getHits().length <= 0) { 24 | return null; 25 | } 26 | SampleEntity user = new SampleEntity(); 27 | user.setId(searchHit.getId()); 28 | user.setMessage((String)searchHit.getSource().get("message")); 29 | chunk.add(user); 30 | } 31 | return new PageImpl(chunk); 32 | } 33 | }); 34 | if(page != null) { 35 | sampleEntities.addAll(page.getContent()); 36 | hasRecords = page.hasNextPage(); 37 | } 38 | else{ 39 | hasRecords = false; 40 | } 41 | } 42 | } 43 | ``` -------------------------------------------------------------------------------- /5/README.md: -------------------------------------------------------------------------------- 1 | # Elasticsearch Repositories 2 | 这一章会详细介绍Elasticsearch repository实现。 3 | -------------------------------------------------------------------------------- /6/6.1.md: -------------------------------------------------------------------------------- 1 | # 附录A 命名空间参考 2 | 3 | #### 元素 4 | 5 | 元素最重要的属性就是base-package,用来定义查找Spring Data repository接口时扫描包的路径。 6 | 7 | Table 3.属性 8 | 9 | |名称|描述| 10 | |:---|:---| 11 | |base-package|定义查找所有继承\*Repository的repository接口时所扫描包的路径,该路径下所有的包都会被扫描。允许使用通配符 12 | |repository-impl-postfix|定义自定义repository实现类的后缀。所有名字是以指定后缀结尾的类都会被看做是自定义repository的实现类。默认值是*Impl* 13 | |query-lookup-strategy|定义创建查询语句的策略,详细请看[查询策略](../4/4.4/4.4.1.md),默认采用*create-if-not-found*策略 14 | |named-queries-location|定义包含外部定义好的查询语句的Properties文件的位置 15 | |consider-nested-repositories|该属性的值决定了是否允许定义嵌套的repository接口。默认值是false 16 | -------------------------------------------------------------------------------- /6/6.2.md: -------------------------------------------------------------------------------- 1 | # 附录B Populators命名空间参考文档 2 | 3 | #### 元素 4 | **允许开发者通过Spring Data repository框架填充数据存储。 5 | 6 | Table 4.Attributes(属性) 7 | 8 | |名称|描述| 9 | |:---|:---| 10 | |locations|定义包含用来读取填充对象的文件的位置 -------------------------------------------------------------------------------- /6/6.3.md: -------------------------------------------------------------------------------- 1 | # 附录C Repository查询关键字 2 | 3 | #### 支持的查询关键字 4 | 下面的表格列出了Spring Data repository查询解析机制支持的查询关键字。某些特定的存储可能不支持全部的关键字。 5 | 6 | Table 5.Query keywords(查询关键字) 7 | 8 | |逻辑关键字|关键字表达式| 9 | |:---|:---| 10 | |AND|And| 11 | |OR|Or| 12 | |AFTER|After, IsAfter| 13 | |BEFORE|Before, IsBefore 14 | |CONTAINING|Containing, IsContaining, Contains 15 | |BETWEEN|Between, IsBetween| 16 | |ENDING_WITH|EndingWith, IsEndingWith, EndsWith| 17 | |EXISTS|Exists| 18 | |FALSE|False, IsFalse| 19 | |GREATER_THAN|GreaterThan, IsGreaterThan| 20 | |GREATER_THAN_EQUALS|GreaterThanEqual, IsGreaterThanEqual| 21 | |IN|In, IsIn| 22 | |IS|Is, Equals, (or no keyword)| 23 | |IS_NOT_NULL|NotNull, IsNotNull| 24 | |IS_NULL|Null, IsNull| 25 | |LESS_THAN|LessThan, IsLessThan| 26 | |LESS_THAN_EQUAL|LessThanEqual, IsLessThanEqual| 27 | |LIKE|Like, IsLike| 28 | |NEAR|Near, IsNear| 29 | |NOT|Not, IsNot 30 | |NOT_IN|NotIn, IsNotIn 31 | |NOT_LIKE|NotLike, IsNotLike 32 | |REGEX|Regex, MatchesRegex, Matches 33 | |STARTING_WITH|StartingWith, IsStartingWith, StartsWith 34 | |TRUE|True, IsTrue 35 | |WITHIN|Within, IsWithin 36 | 37 | -------------------------------------------------------------------------------- /6/6.4.md: -------------------------------------------------------------------------------- 1 | # 附录D Repository查询返回类型 2 | 3 | #### 支持的查询返回类型 4 | 5 | 下面的表格列出了Spring Data repositories支持的返回类型。某些特定的存储可能不支持全部的返回类型。 6 | 7 | >只有支持地理空间查询的数据存储才支持GeoResult,GeoResults,GeoPage等返回类型 8 | 9 | Table 6.Query return types(查询返回值) 10 | 11 | |返回值类型|描述| 12 | |:---|:---| 13 | |void|表示没有返回值| 14 | |Primitives|基本的Java类型 15 | |Wrapper types|Java的包装类 16 | |T|最多只返回一个实体。没有查询结果时返回null。如果超过了一个结果会抛出IncorrectResultSizeDataAccessException的异常| 17 | |Iterator|一个迭代器| 18 | |Collection|一个集合| 19 | |List|一个列表| 20 | |Optional|返回Java 8或Guava中的Optional类。查询方法的返回结果最多只能有一个。如果超过了一个结果会抛出IncorrectResultSizeDataAccessException的异常 21 | |Stream|Java 8引入的Stream类 22 | |Future|一个Future类,查询方法需要带有@Async注解,并开启Spring异步执行方法的功能| 23 | |CompletableFuture|返回Java8中新引入的CompletableFuture类,查询方法需要带有@Async注解,并开启Spring异步执行方法的功能 24 | |ListenableFuture|返回org.springframework.util.concurrent.ListenableFuture类,查询方法需要带有@Async注解,并开启Spring异步执行方法的功能 25 | |Slice|返回指定大小的数据和是否还有可用数据的信息。需要方法带有Pageable类型的参数| 26 | |Page|在Slice的基础上附加返回总数等信息。需要方法带有Pageable类型的参数 27 | |GeoResult|返回结果会附带诸如到相关地点距离等信息 28 | |GeoResults|返回GeoResult的列表,并附带到相关地点平均距离等信息 29 | |GeoPage|分页返回GeoResult,并附带到相关地点平均距离等信息 30 | -------------------------------------------------------------------------------- /6/README.md: -------------------------------------------------------------------------------- 1 | # 附录 2 | -------------------------------------------------------------------------------- /Preface/README.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 3 | >Spring Data Elasticsearch为文档的存储,查询,排序和统计提供了一个高度抽象的模板。在使用中,你会发现Spring Data Elasticsearch和Spring Data Solr/Mongodb有许多相似之处。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | >因为工作需要学习Elasticsearch, 发现关于Spring-Data-Elasticsearch的文档非常少, 而且没有对应官方文档的中译版本,所以利用早起的空闲时间翻译一下。基于1.3.2.RELEASE版本,如果对Spring Data的其他模块(eg:Spring Data Jpa)比较了解,可以直接看[第五章](5/README.md)。 4 | 5 | --------------------------------- 6 | 7 | 英文原版地址:[Spring Data Elasticsearch](http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html) 8 | 9 | --------------------------------- 10 | spring-data-elasticsearch 例子:[github](https://github.com/BioMedCentralLtd/spring-data-elasticsearch-sample-application) 11 | spring-data-elasticsearch 与 Spring web结合 例子:[github](https://github.com/giraffe0813/spring-data-es-web) 12 | 13 | --------------------------------- 14 | 15 | 下载地址:[download](https://www.gitbook.com/book/giraffe0813/spring-data-elasticsearch/details) 16 | 阅读地址:[http://es.yemengying.com](http://es.yemengying.com) 17 | 博客地址:[giraffe's home](http://yemengying.com) 18 | 19 | --------------------------------- 20 | 参考文档 21 | 22 | * http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-jpa/ 23 | * http://leo-suen.iteye.com/blog/1991305 24 | 25 | --------------------------------- 26 | 27 | 译者:[giraffe0813](https://github.com/giraffe0813) 28 | 29 | --------------------------------- 30 | 31 | 项目地址: 32 | [github](https://github.com/giraffe0813/Spring-Data-Elasticsearch) 33 | [gitbook](https://www.gitbook.com/book/giraffe0813/spring-data-elasticsearch/details) 34 | 35 | --------------------------------- 36 | 37 | 关键字约定: 38 | 39 | * domain class -> 域对象 40 | * query builder -> 查询构造器 41 | 42 | --------------------------------- 43 | 44 | 说明: 45 | 由于英文水平有限,且对querydsl等内容并不太了解,可能存在翻译有误的地方,请见谅,欢迎提issue 46 | 47 | --------------------------------- 48 | 49 | 50 | 51 | Created by [giraffe0813](https://github.com/giraffe0813) 52 | This is a book powered by [GitBook](https://github.com/GitbookIO/gitbook). 53 | 54 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # SUMMARY 2 | 3 | * [前言](Preface/README.md) 4 | * [项目元数据](2/README.md) 5 | * [使用条件](3/README.md) 6 | * [玩转Spring Data Repositories](4/README.md) 7 | * [核心概念](4/4.1.md) 8 | * [查询方法](4/4.2.md) 9 | * [repository接口定义](4/4.3.md) 10 | * [调整repository定义](4/4.3/4.3.1.md) 11 | * [定义查询方法](4/4.4.md) 12 | * [查询策略](4/4.4/4.4.1.md) 13 | * [创建查询](4/4.4/4.4.2.md) 14 | * [属性表达式](4/4.4/4.4.3.md) 15 | * [处理特殊参数](4/4.4/4.4.4.md) 16 | * [限定查询结果集大小](4/4.4/4.4.5.md) 17 | * [Stream处理查询结果](4/4.4/4.4.6.md) 18 | * [异步处理查询结果](4/4.4/4.4.7.md) 19 | * [创建repository实例](4/4.5.md) 20 | * [XML配置](4/4.5/4.5.1.md) 21 | * [JavaConfig](4/4.5/4.5.2.md) 22 | * [独立使用](4/4.5/4.5.3.md) 23 | * [自定义repository实现](4/4.6.md) 24 | * [为单一的repositories添加自定义方法](4/4.6/4.6.1.md) 25 | * [为所有的repositories添加自定义方法](4/4.6/4.6.2.md) 26 | * [扩展Spring Data](4/4.7.md) 27 | * [WEB支持](4/4.7/4.7.1.md) 28 | * [Repository填充](4/4.7/4.7.2.md) 29 | * [Elasticsearch Repositories](5/README.md) 30 | * [介绍](5/5.1.md) 31 | * [Spring命名空间](5/5.1/5.1.1.md) 32 | * [基于注解的配置](5/5.1/5.1.2.md) 33 | * [使用CDI](5/5.1/5.1.3.md) 34 | * [查询方法](5/5.2.md) 35 | * [查询策略](5/5.2/5.2.1.md) 36 | * [创建查询](5/5.2/5.2.2.md) 37 | * [使用@Query注解](5/5.2/5.2.3.md) 38 | * [其他Elasticsearch操作的支持](5/5.3.md) 39 | * [构建Filter](5/5.3/5.3.1.md) 40 | * [利用Scan和Scroll处理大结果集](5/5.3/5.3.2.md) 41 | * [附录](6/README.md) 42 | * [附录A 命名空间参考文档](6/6.1.md) 43 | * [附录B Populators命名空间参考文档](6/6.2.md) 44 | * [附录C Repository查询关键字](6/6.3.md) 45 | * [附录D Repository查询返回类型](6/6.4.md) 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /_book/1/README.md: -------------------------------------------------------------------------------- 1 | # 1 项目元数据 2 | -------------------------------------------------------------------------------- /_book/3/3.1.md: -------------------------------------------------------------------------------- 1 | # 3.1 核心概念 2 | -------------------------------------------------------------------------------- /_book/3/3.2.md: -------------------------------------------------------------------------------- 1 | # 3.2 查询方法 2 | -------------------------------------------------------------------------------- /_book/3/3.3.md: -------------------------------------------------------------------------------- 1 | # 3.3 repository接口定义 2 | -------------------------------------------------------------------------------- /_book/3/3.3/3.3.1.md: -------------------------------------------------------------------------------- 1 | # 3.3.1 调整repository定义 2 | -------------------------------------------------------------------------------- /_book/3/3.4.md: -------------------------------------------------------------------------------- 1 | # 3.4 定义查询方法 2 | -------------------------------------------------------------------------------- /_book/3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 使用条件 | README 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
62 | 63 | 64 |
65 | 812 |
813 | 814 |
815 |
816 | 826 | 827 |
828 |
829 | 830 | 831 |
832 | 833 |

使用条件

834 |

需要使用Elasticsearch 0.20.2及以上的版本

835 | 836 | 837 |
838 | 839 | 840 |
841 |
842 |
843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 |
851 |
852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 890 | 891 | 892 | 893 | 894 | 895 | -------------------------------------------------------------------------------- /_book/4/4.7/4.7.3.md: -------------------------------------------------------------------------------- 1 | # 保留网络支持 2 | -------------------------------------------------------------------------------- /_book/5/5.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 介绍 | README 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
62 | 63 | 64 |
65 | 812 |
813 | 814 |
815 |
816 | 826 | 827 |
828 |
829 | 830 | 831 |
832 | 833 |

介绍

834 | 835 | 836 |
837 | 838 | 839 |
840 |
841 |
842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 |
850 |
851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 889 | 890 | 891 | 892 | 893 | 894 | -------------------------------------------------------------------------------- /_book/5/5.2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 查询方法 | README 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
62 | 63 | 64 |
65 | 812 |
813 | 814 |
815 |
816 | 826 | 827 |
828 |
829 | 830 | 831 |
832 | 833 |

查询方法

834 | 835 | 836 |
837 | 838 | 839 |
840 |
841 |
842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 |
850 |
851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 889 | 890 | 891 | 892 | 893 | 894 | -------------------------------------------------------------------------------- /_book/6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 附录 | README 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
62 | 63 | 64 |
65 | 812 |
813 | 814 |
815 |
816 | 826 | 827 |
828 |
829 | 830 | 831 |
832 | 833 |

附录

834 | 835 | 836 |
837 | 838 | 839 |
840 |
841 |
842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 |
850 |
851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 889 | 890 | 891 | 892 | 893 | 894 | -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giraffe0813/Spring-Data-Elasticsearch/971e7591fed15eaa732db1f7ceb1ddc85c4d82d4/_book/gitbook/fonts/fontawesome/FontAwesome.otf -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giraffe0813/Spring-Data-Elasticsearch/971e7591fed15eaa732db1f7ceb1ddc85c4d82d4/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giraffe0813/Spring-Data-Elasticsearch/971e7591fed15eaa732db1f7ceb1ddc85c4d82d4/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giraffe0813/Spring-Data-Elasticsearch/971e7591fed15eaa732db1f7ceb1ddc85c4d82d4/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /_book/gitbook/images/apple-touch-icon-precomposed-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giraffe0813/Spring-Data-Elasticsearch/971e7591fed15eaa732db1f7ceb1ddc85c4d82d4/_book/gitbook/images/apple-touch-icon-precomposed-152.png -------------------------------------------------------------------------------- /_book/gitbook/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giraffe0813/Spring-Data-Elasticsearch/971e7591fed15eaa732db1f7ceb1ddc85c4d82d4/_book/gitbook/images/favicon.ico -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-disqus/plugin.css: -------------------------------------------------------------------------------- 1 | #disqus_thread { 2 | margin: 5px 15px; 3 | margin-top: 30px; 4 | } 5 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-disqus/plugin.js: -------------------------------------------------------------------------------- 1 | require([ 2 | "gitbook", 3 | "jQuery" 4 | ], function(gitbook, $) { 5 | var use_identifier = false; 6 | 7 | function resetDisqus() { 8 | var $disqusDiv = $("
", { 9 | "id": "disqus_thread" 10 | }); 11 | $(".book-body .page-inner").append($disqusDiv); 12 | 13 | if (typeof DISQUS !== "undefined") { 14 | DISQUS.reset({ 15 | reload: true, 16 | config: function () { 17 | this.language = $('html').attr('lang') || "en"; 18 | this.page.url = window.location.href; 19 | 20 | if (use_identifier) { 21 | this.page.identifier = currentUrl(); 22 | } 23 | } 24 | }); 25 | } 26 | } 27 | 28 | function joinURL(baseUrl, url) { 29 | var theUrl = new URI(url); 30 | if (theUrl.is("relative")) { 31 | theUrl = theUrl.absoluteTo(baseUrl); 32 | } 33 | return theUrl.toString(); 34 | } 35 | 36 | function currentUrl() { 37 | var location = new URI(window.location.href), 38 | base = joinURL(window.location.href, gitbook.state.basePath), 39 | current = location.relativeTo(base).toString(), 40 | language = $('html').attr('lang'), 41 | parent = joinURL(base, '..'), 42 | folder = new URI(base).relativeTo(parent).toString(); 43 | 44 | // If parent folder is the same as language, we assume translated books 45 | if (folder.replace(/\/$/, "") === language) { 46 | current = folder + current; 47 | } 48 | 49 | return current; 50 | } 51 | 52 | gitbook.events.bind("start", function(e, config) { 53 | config.disqus = config.disqus || {}; 54 | var disqus_shortname = config.disqus.shortName; 55 | var disqus_config = function() { 56 | this.language = $('html').attr('lang') || "en"; 57 | }; 58 | 59 | if (config.disqus.useIdentifier) { 60 | use_identifier = true; 61 | var disqus_identifier = currentUrl(); 62 | } 63 | 64 | /* * * DON'T EDIT BELOW THIS LINE * * */ 65 | (function() { 66 | var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; 67 | dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; 68 | (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); 69 | })(); 70 | 71 | resetDisqus(); 72 | }); 73 | 74 | gitbook.events.bind("page.change", resetDisqus); 75 | }); 76 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-fontsettings/buttons.js: -------------------------------------------------------------------------------- 1 | require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { 2 | var fontState; 3 | 4 | var THEMES = { 5 | "white": 0, 6 | "sepia": 1, 7 | "night": 2 8 | }; 9 | 10 | var FAMILY = { 11 | "serif": 0, 12 | "sans": 1 13 | }; 14 | 15 | // Save current font settings 16 | function saveFontSettings() { 17 | gitbook.storage.set("fontState", fontState); 18 | update(); 19 | } 20 | 21 | // Increase font size 22 | function enlargeFontSize(e) { 23 | e.preventDefault(); 24 | if (fontState.size >= 4) return; 25 | 26 | fontState.size++; 27 | saveFontSettings(); 28 | }; 29 | 30 | // Decrease font size 31 | function reduceFontSize(e) { 32 | e.preventDefault(); 33 | if (fontState.size <= 0) return; 34 | 35 | fontState.size--; 36 | saveFontSettings(); 37 | }; 38 | 39 | // Change font family 40 | function changeFontFamily(index, e) { 41 | e.preventDefault(); 42 | 43 | fontState.family = index; 44 | saveFontSettings(); 45 | }; 46 | 47 | // Change type of color 48 | function changeColorTheme(index, e) { 49 | e.preventDefault(); 50 | 51 | var $book = $(".book"); 52 | 53 | if (fontState.theme !== 0) 54 | $book.removeClass("color-theme-"+fontState.theme); 55 | 56 | fontState.theme = index; 57 | if (fontState.theme !== 0) 58 | $book.addClass("color-theme-"+fontState.theme); 59 | 60 | saveFontSettings(); 61 | }; 62 | 63 | function update() { 64 | var $book = gitbook.state.$book; 65 | 66 | $(".font-settings .font-family-list li").removeClass("active"); 67 | $(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active"); 68 | 69 | $book[0].className = $book[0].className.replace(/\bfont-\S+/g, ''); 70 | $book.addClass("font-size-"+fontState.size); 71 | $book.addClass("font-family-"+fontState.family); 72 | 73 | if(fontState.theme !== 0) { 74 | $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, ''); 75 | $book.addClass("color-theme-"+fontState.theme); 76 | } 77 | }; 78 | 79 | function init(config) { 80 | var $bookBody, $book; 81 | 82 | //Find DOM elements. 83 | $book = gitbook.state.$book; 84 | $bookBody = $book.find(".book-body"); 85 | 86 | // Instantiate font state object 87 | fontState = gitbook.storage.get("fontState", { 88 | size: config.size || 2, 89 | family: FAMILY[config.family || "sans"], 90 | theme: THEMES[config.theme || "white"] 91 | }); 92 | 93 | update(); 94 | }; 95 | 96 | 97 | gitbook.events.bind("start", function(e, config) { 98 | var opts = config.fontsettings; 99 | 100 | // Create buttons in toolbar 101 | gitbook.toolbar.createButton({ 102 | icon: 'fa fa-font', 103 | label: 'Font Settings', 104 | className: 'font-settings', 105 | dropdown: [ 106 | [ 107 | { 108 | text: 'A', 109 | className: 'font-reduce', 110 | onClick: reduceFontSize 111 | }, 112 | { 113 | text: 'A', 114 | className: 'font-enlarge', 115 | onClick: enlargeFontSize 116 | } 117 | ], 118 | [ 119 | { 120 | text: 'Serif', 121 | onClick: _.partial(changeFontFamily, 0) 122 | }, 123 | { 124 | text: 'Sans', 125 | onClick: _.partial(changeFontFamily, 1) 126 | } 127 | ], 128 | [ 129 | { 130 | text: 'White', 131 | onClick: _.partial(changeColorTheme, 0) 132 | }, 133 | { 134 | text: 'Sepia', 135 | onClick: _.partial(changeColorTheme, 1) 136 | }, 137 | { 138 | text: 'Night', 139 | onClick: _.partial(changeColorTheme, 2) 140 | } 141 | ] 142 | ] 143 | }); 144 | 145 | 146 | // Init current settings 147 | init(opts); 148 | }); 149 | }); 150 | 151 | 152 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-fontsettings/website.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Theme 1 3 | */ 4 | .color-theme-1 .dropdown-menu { 5 | background-color: #111111; 6 | border-color: #7e888b; 7 | } 8 | .color-theme-1 .dropdown-menu .dropdown-caret .caret-inner { 9 | border-bottom: 9px solid #111111; 10 | } 11 | .color-theme-1 .dropdown-menu .buttons { 12 | border-color: #7e888b; 13 | } 14 | .color-theme-1 .dropdown-menu .button { 15 | color: #afa790; 16 | } 17 | .color-theme-1 .dropdown-menu .button:hover { 18 | color: #73553c; 19 | } 20 | /* 21 | * Theme 2 22 | */ 23 | .color-theme-2 .dropdown-menu { 24 | background-color: #2d3143; 25 | border-color: #272a3a; 26 | } 27 | .color-theme-2 .dropdown-menu .dropdown-caret .caret-inner { 28 | border-bottom: 9px solid #2d3143; 29 | } 30 | .color-theme-2 .dropdown-menu .buttons { 31 | border-color: #272a3a; 32 | } 33 | .color-theme-2 .dropdown-menu .button { 34 | color: #62677f; 35 | } 36 | .color-theme-2 .dropdown-menu .button:hover { 37 | color: #f4f4f5; 38 | } 39 | .book .book-header .font-settings .font-enlarge { 40 | line-height: 30px; 41 | font-size: 1.4em; 42 | } 43 | .book .book-header .font-settings .font-reduce { 44 | line-height: 30px; 45 | font-size: 1em; 46 | } 47 | .book.color-theme-1 .book-body { 48 | color: #704214; 49 | background: #f3eacb; 50 | } 51 | .book.color-theme-1 .book-body .page-wrapper .page-inner section { 52 | background: #f3eacb; 53 | } 54 | .book.color-theme-2 .book-body { 55 | color: #bdcadb; 56 | background: #1c1f2b; 57 | } 58 | .book.color-theme-2 .book-body .page-wrapper .page-inner section { 59 | background: #1c1f2b; 60 | } 61 | .book.font-size-0 .book-body .page-inner section { 62 | font-size: 1.2rem; 63 | } 64 | .book.font-size-1 .book-body .page-inner section { 65 | font-size: 1.4rem; 66 | } 67 | .book.font-size-2 .book-body .page-inner section { 68 | font-size: 1.6rem; 69 | } 70 | .book.font-size-3 .book-body .page-inner section { 71 | font-size: 2.2rem; 72 | } 73 | .book.font-size-4 .book-body .page-inner section { 74 | font-size: 4rem; 75 | } 76 | .book.font-family-0 { 77 | font-family: Georgia, serif; 78 | } 79 | .book.font-family-1 { 80 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 81 | } 82 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal { 83 | color: #704214; 84 | } 85 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a { 86 | color: inherit; 87 | } 88 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 89 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2, 90 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3, 91 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4, 92 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5, 93 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 94 | color: inherit; 95 | } 96 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, 97 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 { 98 | border-color: inherit; 99 | } 100 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { 101 | color: inherit; 102 | } 103 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr { 104 | background-color: inherit; 105 | } 106 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote { 107 | border-color: inherit; 108 | } 109 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, 110 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { 111 | background: #fdf6e3; 112 | color: #657b83; 113 | border-color: #f8df9c; 114 | } 115 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight { 116 | background-color: inherit; 117 | } 118 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th, 119 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td { 120 | border-color: #f5d06c; 121 | } 122 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr { 123 | color: inherit; 124 | background-color: #fdf6e3; 125 | border-color: #444444; 126 | } 127 | .book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 128 | background-color: #fbeecb; 129 | } 130 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal { 131 | color: #bdcadb; 132 | } 133 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a { 134 | color: #3eb1d0; 135 | } 136 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 137 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2, 138 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3, 139 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4, 140 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5, 141 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 142 | color: #fffffa; 143 | } 144 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, 145 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 { 146 | border-color: #373b4e; 147 | } 148 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { 149 | color: #373b4e; 150 | } 151 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr { 152 | background-color: #373b4e; 153 | } 154 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote { 155 | border-color: #373b4e; 156 | } 157 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, 158 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { 159 | color: #9dbed8; 160 | background: #2d3143; 161 | border-color: #2d3143; 162 | } 163 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight { 164 | background-color: #282a39; 165 | } 166 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th, 167 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td { 168 | border-color: #3b3f54; 169 | } 170 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr { 171 | color: #b6c2d2; 172 | background-color: #2d3143; 173 | border-color: #3b3f54; 174 | } 175 | .book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { 176 | background-color: #35394b; 177 | } 178 | .book.color-theme-1 .book-header { 179 | color: #afa790; 180 | background: transparent; 181 | } 182 | .book.color-theme-1 .book-header .btn { 183 | color: #afa790; 184 | } 185 | .book.color-theme-1 .book-header .btn:hover { 186 | color: #73553c; 187 | background: none; 188 | } 189 | .book.color-theme-1 .book-header h1 { 190 | color: #704214; 191 | } 192 | .book.color-theme-2 .book-header { 193 | color: #7e888b; 194 | background: transparent; 195 | } 196 | .book.color-theme-2 .book-header .btn { 197 | color: #3b3f54; 198 | } 199 | .book.color-theme-2 .book-header .btn:hover { 200 | color: #fffff5; 201 | background: none; 202 | } 203 | .book.color-theme-2 .book-header h1 { 204 | color: #bdcadb; 205 | } 206 | .book.color-theme-1 .book-body .navigation { 207 | color: #afa790; 208 | } 209 | .book.color-theme-1 .book-body .navigation:hover { 210 | color: #73553c; 211 | } 212 | .book.color-theme-2 .book-body .navigation { 213 | color: #383f52; 214 | } 215 | .book.color-theme-2 .book-body .navigation:hover { 216 | color: #fffff5; 217 | } 218 | /* 219 | * Theme 1 220 | */ 221 | .book.color-theme-1 .book-summary { 222 | color: #afa790; 223 | background: #111111; 224 | border-right: 1px solid rgba(0, 0, 0, 0.07); 225 | } 226 | .book.color-theme-1 .book-summary .book-search { 227 | background: transparent; 228 | } 229 | .book.color-theme-1 .book-summary .book-search input, 230 | .book.color-theme-1 .book-summary .book-search input:focus { 231 | border: 1px solid transparent; 232 | } 233 | .book.color-theme-1 .book-summary ul.summary li.divider { 234 | background: #7e888b; 235 | box-shadow: none; 236 | } 237 | .book.color-theme-1 .book-summary ul.summary li i.fa-check { 238 | color: #33cc33; 239 | } 240 | .book.color-theme-1 .book-summary ul.summary li.done > a { 241 | color: #877f6a; 242 | } 243 | .book.color-theme-1 .book-summary ul.summary li a, 244 | .book.color-theme-1 .book-summary ul.summary li span { 245 | color: #877f6a; 246 | background: transparent; 247 | font-weight: normal; 248 | } 249 | .book.color-theme-1 .book-summary ul.summary li.active > a, 250 | .book.color-theme-1 .book-summary ul.summary li a:hover { 251 | color: #704214; 252 | background: transparent; 253 | font-weight: normal; 254 | } 255 | /* 256 | * Theme 2 257 | */ 258 | .book.color-theme-2 .book-summary { 259 | color: #bcc1d2; 260 | background: #2d3143; 261 | border-right: none; 262 | } 263 | .book.color-theme-2 .book-summary .book-search { 264 | background: transparent; 265 | } 266 | .book.color-theme-2 .book-summary .book-search input, 267 | .book.color-theme-2 .book-summary .book-search input:focus { 268 | border: 1px solid transparent; 269 | } 270 | .book.color-theme-2 .book-summary ul.summary li.divider { 271 | background: #272a3a; 272 | box-shadow: none; 273 | } 274 | .book.color-theme-2 .book-summary ul.summary li i.fa-check { 275 | color: #33cc33; 276 | } 277 | .book.color-theme-2 .book-summary ul.summary li.done > a { 278 | color: #62687f; 279 | } 280 | .book.color-theme-2 .book-summary ul.summary li a, 281 | .book.color-theme-2 .book-summary ul.summary li span { 282 | color: #c1c6d7; 283 | background: transparent; 284 | font-weight: 600; 285 | } 286 | .book.color-theme-2 .book-summary ul.summary li.active > a, 287 | .book.color-theme-2 .book-summary ul.summary li a:hover { 288 | color: #f4f4f5; 289 | background: #252737; 290 | font-weight: 600; 291 | } 292 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-highlight/ebook.css: -------------------------------------------------------------------------------- 1 | pre, 2 | code { 3 | /* http://jmblog.github.io/color-themes-for-highlightjs */ 4 | /* Tomorrow Comment */ 5 | /* Tomorrow Red */ 6 | /* Tomorrow Orange */ 7 | /* Tomorrow Yellow */ 8 | /* Tomorrow Green */ 9 | /* Tomorrow Aqua */ 10 | /* Tomorrow Blue */ 11 | /* Tomorrow Purple */ 12 | } 13 | pre .hljs-comment, 14 | code .hljs-comment, 15 | pre .hljs-title, 16 | code .hljs-title { 17 | color: #8e908c; 18 | } 19 | pre .hljs-variable, 20 | code .hljs-variable, 21 | pre .hljs-attribute, 22 | code .hljs-attribute, 23 | pre .hljs-tag, 24 | code .hljs-tag, 25 | pre .hljs-regexp, 26 | code .hljs-regexp, 27 | pre .ruby .hljs-constant, 28 | code .ruby .hljs-constant, 29 | pre .xml .hljs-tag .hljs-title, 30 | code .xml .hljs-tag .hljs-title, 31 | pre .xml .hljs-pi, 32 | code .xml .hljs-pi, 33 | pre .xml .hljs-doctype, 34 | code .xml .hljs-doctype, 35 | pre .html .hljs-doctype, 36 | code .html .hljs-doctype, 37 | pre .css .hljs-id, 38 | code .css .hljs-id, 39 | pre .css .hljs-class, 40 | code .css .hljs-class, 41 | pre .css .hljs-pseudo, 42 | code .css .hljs-pseudo { 43 | color: #c82829; 44 | } 45 | pre .hljs-number, 46 | code .hljs-number, 47 | pre .hljs-preprocessor, 48 | code .hljs-preprocessor, 49 | pre .hljs-pragma, 50 | code .hljs-pragma, 51 | pre .hljs-built_in, 52 | code .hljs-built_in, 53 | pre .hljs-literal, 54 | code .hljs-literal, 55 | pre .hljs-params, 56 | code .hljs-params, 57 | pre .hljs-constant, 58 | code .hljs-constant { 59 | color: #f5871f; 60 | } 61 | pre .ruby .hljs-class .hljs-title, 62 | code .ruby .hljs-class .hljs-title, 63 | pre .css .hljs-rules .hljs-attribute, 64 | code .css .hljs-rules .hljs-attribute { 65 | color: #eab700; 66 | } 67 | pre .hljs-string, 68 | code .hljs-string, 69 | pre .hljs-value, 70 | code .hljs-value, 71 | pre .hljs-inheritance, 72 | code .hljs-inheritance, 73 | pre .hljs-header, 74 | code .hljs-header, 75 | pre .ruby .hljs-symbol, 76 | code .ruby .hljs-symbol, 77 | pre .xml .hljs-cdata, 78 | code .xml .hljs-cdata { 79 | color: #718c00; 80 | } 81 | pre .css .hljs-hexcolor, 82 | code .css .hljs-hexcolor { 83 | color: #3e999f; 84 | } 85 | pre .hljs-function, 86 | code .hljs-function, 87 | pre .python .hljs-decorator, 88 | code .python .hljs-decorator, 89 | pre .python .hljs-title, 90 | code .python .hljs-title, 91 | pre .ruby .hljs-function .hljs-title, 92 | code .ruby .hljs-function .hljs-title, 93 | pre .ruby .hljs-title .hljs-keyword, 94 | code .ruby .hljs-title .hljs-keyword, 95 | pre .perl .hljs-sub, 96 | code .perl .hljs-sub, 97 | pre .javascript .hljs-title, 98 | code .javascript .hljs-title, 99 | pre .coffeescript .hljs-title, 100 | code .coffeescript .hljs-title { 101 | color: #4271ae; 102 | } 103 | pre .hljs-keyword, 104 | code .hljs-keyword, 105 | pre .javascript .hljs-function, 106 | code .javascript .hljs-function { 107 | color: #8959a8; 108 | } 109 | pre .hljs, 110 | code .hljs { 111 | display: block; 112 | background: white; 113 | color: #4d4d4c; 114 | padding: 0.5em; 115 | } 116 | pre .coffeescript .javascript, 117 | code .coffeescript .javascript, 118 | pre .javascript .xml, 119 | code .javascript .xml, 120 | pre .tex .hljs-formula, 121 | code .tex .hljs-formula, 122 | pre .xml .javascript, 123 | code .xml .javascript, 124 | pre .xml .vbscript, 125 | code .xml .vbscript, 126 | pre .xml .css, 127 | code .xml .css, 128 | pre .xml .hljs-cdata, 129 | code .xml .hljs-cdata { 130 | opacity: 0.5; 131 | } 132 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-livereload/plugin.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var newEl = document.createElement('script'), 3 | firstScriptTag = document.getElementsByTagName('script')[0]; 4 | 5 | if (firstScriptTag) { 6 | newEl.async = 1; 7 | newEl.src = '//' + window.location.hostname + ':35729/livereload.js'; 8 | firstScriptTag.parentNode.insertBefore(newEl, firstScriptTag); 9 | } 10 | 11 | })(); 12 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-search/lunr.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 0.5.12 3 | * Copyright (C) 2015 Oliver Nightingale 4 | * MIT Licensed 5 | * @license 6 | */ 7 | !function(){var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.5.12",t.utils={},t.utils.warn=function(t){return function(e){t.console&&console.warn&&console.warn(e)}}(this),t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var t=Array.prototype.slice.call(arguments),e=t.pop(),n=t;if("function"!=typeof e)throw new TypeError("last argument must be a function");n.forEach(function(t){this.hasHandler(t)||(this.events[t]=[]),this.events[t].push(e)},this)},t.EventEmitter.prototype.removeListener=function(t,e){if(this.hasHandler(t)){var n=this.events[t].indexOf(e);this.events[t].splice(n,1),this.events[t].length||delete this.events[t]}},t.EventEmitter.prototype.emit=function(t){if(this.hasHandler(t)){var e=Array.prototype.slice.call(arguments,1);this.events[t].forEach(function(t){t.apply(void 0,e)})}},t.EventEmitter.prototype.hasHandler=function(t){return t in this.events},t.tokenizer=function(t){return arguments.length&&null!=t&&void 0!=t?Array.isArray(t)?t.map(function(t){return t.toLowerCase()}):t.toString().trim().toLowerCase().split(/[\s\-]+/):[]},t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.registeredFunctions[e];if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");this._stack.splice(i,0,n)},t.Pipeline.prototype.remove=function(t){var e=this._stack.indexOf(t);-1!=e&&this._stack.splice(e,1)},t.Pipeline.prototype.run=function(t){for(var e=[],n=t.length,i=this._stack.length,o=0;n>o;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;n', { 41 | 'class': 'book-search', 42 | 'role': 'search' 43 | }); 44 | 45 | $searchInput = $('', { 46 | 'type': 'text', 47 | 'class': 'form-control', 48 | 'val': value, 49 | 'placeholder': 'Type to search' 50 | }); 51 | 52 | $searchInput.appendTo($searchForm); 53 | $searchForm.prependTo(gitbook.state.$book.find('.book-summary')); 54 | } 55 | 56 | // Return true if search is open 57 | function isSearchOpen() { 58 | return gitbook.state.$book.hasClass("with-search"); 59 | } 60 | 61 | // Toggle the search 62 | function toggleSearch(_state) { 63 | if (isSearchOpen() === _state) return; 64 | 65 | gitbook.state.$book.toggleClass("with-search", _state); 66 | 67 | // If search bar is open: focus input 68 | if (isSearchOpen()) { 69 | gitbook.sidebar.toggle(true); 70 | $searchInput.focus(); 71 | } else { 72 | $searchInput.blur(); 73 | $searchInput.val(""); 74 | gitbook.sidebar.filter(null); 75 | } 76 | } 77 | 78 | // Recover current search when page changed 79 | function recoverSearch() { 80 | var keyword = gitbook.storage.get("keyword", ""); 81 | 82 | createForm(keyword); 83 | 84 | if (keyword.length > 0) { 85 | if(!isSearchOpen()) { 86 | toggleSearch(); 87 | } 88 | gitbook.sidebar.filter(_.pluck(search(keyword), "path")); 89 | } 90 | }; 91 | 92 | 93 | gitbook.events.bind("start", function(config) { 94 | // Pre-fetch search index and create the form 95 | fetchIndex(); 96 | createForm(); 97 | 98 | // Type in search bar 99 | $(document).on("keyup", ".book-search input", function(e) { 100 | var key = (e.keyCode ? e.keyCode : e.which); 101 | var q = $(this).val(); 102 | 103 | if (key == 27) { 104 | e.preventDefault(); 105 | toggleSearch(false); 106 | return; 107 | } 108 | if (q.length == 0) { 109 | gitbook.sidebar.filter(null); 110 | gitbook.storage.remove("keyword"); 111 | } else { 112 | var results = search(q); 113 | gitbook.sidebar.filter( 114 | _.pluck(results, "path") 115 | ); 116 | gitbook.storage.set("keyword", q); 117 | } 118 | }); 119 | 120 | // Create the toggle search button 121 | gitbook.toolbar.createButton({ 122 | icon: 'fa fa-search', 123 | label: 'Search', 124 | position: 'left', 125 | onClick: toggleSearch 126 | }); 127 | 128 | // Bind keyboard to toggle search 129 | gitbook.keyboard.bind(['f'], toggleSearch) 130 | }); 131 | 132 | gitbook.events.bind("page.change", recoverSearch); 133 | }); 134 | 135 | 136 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-sharing/buttons.js: -------------------------------------------------------------------------------- 1 | require(["gitbook", "lodash"], function(gitbook, _) { 2 | var SITES = { 3 | 'facebook': { 4 | 'label': 'Facebook', 5 | 'icon': 'fa fa-facebook', 6 | 'onClick': function(e) { 7 | e.preventDefault(); 8 | window.open("http://www.facebook.com/sharer/sharer.php?s=100&p[url]="+encodeURIComponent(location.href)); 9 | } 10 | }, 11 | 'twitter': { 12 | 'label': 'Twitter', 13 | 'icon': 'fa fa-twitter', 14 | 'onClick': function(e) { 15 | e.preventDefault(); 16 | window.open("http://twitter.com/home?status="+encodeURIComponent(document.title+" "+location.href)); 17 | } 18 | }, 19 | 'google': { 20 | 'label': 'Google+', 21 | 'icon': 'fa fa-google-plus', 22 | 'onClick': function(e) { 23 | e.preventDefault(); 24 | window.open("https://plus.google.com/share?url="+encodeURIComponent(location.href)); 25 | } 26 | }, 27 | 'weibo': { 28 | 'label': 'Weibo', 29 | 'icon': 'fa fa-weibo', 30 | 'onClick': function(e) { 31 | e.preventDefault(); 32 | window.open("http://service.weibo.com/share/share.php?content=utf-8&url="+encodeURIComponent(location.href)+"&title="+encodeURIComponent(document.title)); 33 | } 34 | }, 35 | 'instapaper': { 36 | 'label': 'Instapaper', 37 | 'icon': 'fa fa-instapaper', 38 | 'onClick': function(e) { 39 | e.preventDefault(); 40 | window.open("http://www.instapaper.com/text?u="+encodeURIComponent(location.href)); 41 | } 42 | }, 43 | 'vk': { 44 | 'label': 'VK', 45 | 'icon': 'fa fa-vk', 46 | 'onClick': function(e) { 47 | e.preventDefault(); 48 | window.open("http://vkontakte.ru/share.php?url="+encodeURIComponent(location.href)); 49 | } 50 | } 51 | }; 52 | 53 | 54 | 55 | gitbook.events.bind("start", function(e, config) { 56 | var opts = config.sharing; 57 | 58 | // Create dropdown menu 59 | var menu = _.chain(opts.all) 60 | .map(function(id) { 61 | var site = SITES[id]; 62 | 63 | return { 64 | text: site.label, 65 | onClick: site.onClick 66 | }; 67 | }) 68 | .compact() 69 | .value(); 70 | 71 | // Create main button with dropdown 72 | if (menu.length > 0) { 73 | gitbook.toolbar.createButton({ 74 | icon: 'fa fa-share-alt', 75 | label: 'Share', 76 | position: 'right', 77 | dropdown: [menu] 78 | }); 79 | } 80 | 81 | // Direct actions to share 82 | _.each(SITES, function(site, sideId) { 83 | if (!opts[sideId]) return; 84 | 85 | gitbook.toolbar.createButton({ 86 | icon: site.icon, 87 | label: site.text, 88 | position: 'right', 89 | onClick: site.onClick 90 | }); 91 | }); 92 | }); 93 | }); 94 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["disqus"], 3 | "pluginsConfig": { 4 | "disqus": { 5 | "shortName": "spring-data-elasticsearch" 6 | } 7 | }, 8 | "language": "zh-hans" 9 | } -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giraffe0813/Spring-Data-Elasticsearch/971e7591fed15eaa732db1f7ceb1ddc85c4d82d4/cover.jpg -------------------------------------------------------------------------------- /node_modules/gitbook-plugin-disqus/.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Deployed apps should consider commenting this line out: 24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 25 | node_modules 26 | -------------------------------------------------------------------------------- /node_modules/gitbook-plugin-disqus/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2014 FriendCode Inc. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /node_modules/gitbook-plugin-disqus/README.md: -------------------------------------------------------------------------------- 1 | # Disqus integration for GitBook 2 | 3 | To use the Disqus plugin in your Gitbook project, add the disqus plugin to the `book.json` file, along with your shortname (you create a shortname for disqus by creating a new website on the [disqus.com](https://disqus.com/) website) 4 | 5 | ``` 6 | { 7 | "plugins": ["disqus"], 8 | "pluginsConfig": { 9 | "disqus": { 10 | "shortName": "XXXXXXX" 11 | } 12 | } 13 | } 14 | ``` 15 | 16 | Then run `gitbook install` to download and install the plugin. 17 | -------------------------------------------------------------------------------- /node_modules/gitbook-plugin-disqus/book/plugin.css: -------------------------------------------------------------------------------- 1 | #disqus_thread { 2 | margin: 5px 15px; 3 | margin-top: 30px; 4 | } 5 | -------------------------------------------------------------------------------- /node_modules/gitbook-plugin-disqus/book/plugin.js: -------------------------------------------------------------------------------- 1 | require([ 2 | "gitbook", 3 | "jQuery" 4 | ], function(gitbook, $) { 5 | var use_identifier = false; 6 | 7 | function resetDisqus() { 8 | var $disqusDiv = $("
", { 9 | "id": "disqus_thread" 10 | }); 11 | $(".book-body .page-inner").append($disqusDiv); 12 | 13 | if (typeof DISQUS !== "undefined") { 14 | DISQUS.reset({ 15 | reload: true, 16 | config: function () { 17 | this.language = $('html').attr('lang') || "en"; 18 | this.page.url = window.location.href; 19 | 20 | if (use_identifier) { 21 | this.page.identifier = currentUrl(); 22 | } 23 | } 24 | }); 25 | } 26 | } 27 | 28 | function joinURL(baseUrl, url) { 29 | var theUrl = new URI(url); 30 | if (theUrl.is("relative")) { 31 | theUrl = theUrl.absoluteTo(baseUrl); 32 | } 33 | return theUrl.toString(); 34 | } 35 | 36 | function currentUrl() { 37 | var location = new URI(window.location.href), 38 | base = joinURL(window.location.href, gitbook.state.basePath), 39 | current = location.relativeTo(base).toString(), 40 | language = $('html').attr('lang'), 41 | parent = joinURL(base, '..'), 42 | folder = new URI(base).relativeTo(parent).toString(); 43 | 44 | // If parent folder is the same as language, we assume translated books 45 | if (folder.replace(/\/$/, "") === language) { 46 | current = folder + current; 47 | } 48 | 49 | return current; 50 | } 51 | 52 | gitbook.events.bind("start", function(e, config) { 53 | config.disqus = config.disqus || {}; 54 | var disqus_shortname = config.disqus.shortName; 55 | var disqus_config = function() { 56 | this.language = $('html').attr('lang') || "en"; 57 | }; 58 | 59 | if (config.disqus.useIdentifier) { 60 | use_identifier = true; 61 | var disqus_identifier = currentUrl(); 62 | } 63 | 64 | /* * * DON'T EDIT BELOW THIS LINE * * */ 65 | (function() { 66 | var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; 67 | dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; 68 | (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); 69 | })(); 70 | 71 | resetDisqus(); 72 | }); 73 | 74 | gitbook.events.bind("page.change", resetDisqus); 75 | }); 76 | -------------------------------------------------------------------------------- /node_modules/gitbook-plugin-disqus/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | book: { 3 | assets: "./book", 4 | js: [ 5 | "https://cdnjs.cloudflare.com/ajax/libs/URI.js/1.16.1/URI.min.js", 6 | "plugin.js" 7 | ], 8 | css: [ 9 | "plugin.css" 10 | ] 11 | } 12 | }; -------------------------------------------------------------------------------- /node_modules/gitbook-plugin-disqus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitbook-plugin-disqus", 3 | "description": "Disqus integration into GitBook", 4 | "main": "index.js", 5 | "version": "0.1.0", 6 | "engines": { 7 | "gitbook": ">=2.5.0" 8 | }, 9 | "homepage": "https://github.com/GitbookIO/plugin-disqus", 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/GitbookIO/plugin-disqus.git" 13 | }, 14 | "license": "Apache-2.0", 15 | "bugs": { 16 | "url": "https://github.com/GitbookIO/plugin-disqus/issues" 17 | }, 18 | "gitbook": { 19 | "properties": { 20 | "shortName": { 21 | "type": "string", 22 | "title": "Website Shortname", 23 | "required": true 24 | }, 25 | "useIdentifier": { 26 | "type": "boolean", 27 | "title": "Use page identifier", 28 | "default": false 29 | } 30 | } 31 | }, 32 | "gitHead": "bd3f256d1ee529764dc7e04e4ad40efd93572008", 33 | "_id": "gitbook-plugin-disqus@0.1.0", 34 | "scripts": {}, 35 | "_shasum": "f6035f9c4987cf5fc9180e05a64435a678296ad6", 36 | "_from": "gitbook-plugin-disqus@0.1.0", 37 | "_npmVersion": "2.14.5", 38 | "_nodeVersion": "0.12.7", 39 | "_npmUser": { 40 | "name": "samypesse", 41 | "email": "samypesse@gmail.com" 42 | }, 43 | "dist": { 44 | "shasum": "f6035f9c4987cf5fc9180e05a64435a678296ad6", 45 | "tarball": "http://registry.npmjs.org/gitbook-plugin-disqus/-/gitbook-plugin-disqus-0.1.0.tgz" 46 | }, 47 | "maintainers": [ 48 | { 49 | "name": "samypesse", 50 | "email": "samypesse@gmail.com" 51 | } 52 | ], 53 | "directories": {}, 54 | "_resolved": "https://registry.npmjs.org/gitbook-plugin-disqus/-/gitbook-plugin-disqus-0.1.0.tgz", 55 | "readme": "ERROR: No README data found!" 56 | } 57 | --------------------------------------------------------------------------------