001package io.ebean; 002 003import io.ebean.search.Match; 004import io.ebean.search.MultiMatch; 005import io.ebean.search.TextCommonTerms; 006import io.ebean.search.TextQueryString; 007import io.ebean.search.TextSimple; 008 009import javax.annotation.Nonnull; 010import javax.annotation.Nullable; 011import javax.persistence.NonUniqueResultException; 012import java.sql.Connection; 013import java.sql.Timestamp; 014import java.util.Collection; 015import java.util.List; 016import java.util.Map; 017import java.util.Optional; 018import java.util.Set; 019import java.util.function.Consumer; 020import java.util.function.Predicate; 021 022/** 023 * List of Expressions that make up a where or having clause. 024 * <p> 025 * An ExpressionList is returned from {@link Query#where()}. 026 * </p> 027 * <p> 028 * The ExpressionList has a list of convenience methods that create the standard 029 * expressions and add them to this list. 030 * </p> 031 * <p> 032 * The ExpressionList also duplicates methods that are found on the Query such 033 * as findList() and order(). The purpose of these methods is provide a fluid 034 * API. The upside of this approach is that you can build and execute a query 035 * via chained methods. The down side is that this ExpressionList object has 036 * more methods than you would initially expect (the ones duplicated from 037 * Query). 038 * </p> 039 * 040 * @see Query#where() 041 */ 042public interface ExpressionList<T> { 043 044 /** 045 * Return the query that owns this expression list. 046 * <p> 047 * This is a convenience method solely to support a fluid API where the 048 * methods are chained together. Adding expressions returns this expression 049 * list and this method can be used after that to return back the original 050 * query so that further things can be added to it. 051 * </p> 052 */ 053 Query<T> query(); 054 055 /** 056 * Controls, if paginated queries should always append an 'order by id' statement at the end to 057 * guarantee a deterministic sort result. This may affect performance. 058 * If this is not enabled, and an orderBy is set on the query, it's up to the programmer that 059 * this query provides a deterministic result. 060 */ 061 Query<T> orderById(boolean orderById); 062 063 /** 064 * Set the order by clause replacing the existing order by clause if there is 065 * one. 066 * <p> 067 * This follows SQL syntax using commas between each property with the 068 * optional asc and desc keywords representing ascending and descending order 069 * respectively. 070 */ 071 ExpressionList<T> order(String orderByClause); 072 073 /** 074 * Set the order by clause replacing the existing order by clause if there is 075 * one. 076 * <p> 077 * This follows SQL syntax using commas between each property with the 078 * optional asc and desc keywords representing ascending and descending order 079 * respectively. 080 */ 081 ExpressionList<T> orderBy(String orderBy); 082 083 /** 084 * Return the OrderBy so that you can append an ascending or descending 085 * property to the order by clause. 086 * <p> 087 * This will never return a null. If no order by clause exists then an 'empty' 088 * OrderBy object is returned. 089 * <p> 090 * This is the same as <code>orderBy()</code> 091 */ 092 OrderBy<T> order(); 093 094 /** 095 * Return the OrderBy so that you can append an ascending or descending 096 * property to the order by clause. 097 * <p> 098 * This will never return a null. If no order by clause exists then an 'empty' 099 * OrderBy object is returned. 100 * <p> 101 * This is the same as <code>order()</code> 102 */ 103 OrderBy<T> orderBy(); 104 105 /** 106 * Deprecated migrate to {@link #orderBy(String)} 107 */ 108 @Deprecated 109 Query<T> setOrderBy(String orderBy); 110 111 /** 112 * Apply the path properties to the query replacing the select and fetch clauses. 113 */ 114 Query<T> apply(FetchPath fetchPath); 115 116 /** 117 * Perform an 'As of' query using history tables to return the object graph 118 * as of a time in the past. 119 * <p> 120 * To perform this query the DB must have underlying history tables. 121 * </p> 122 * 123 * @param asOf the date time in the past at which you want to view the data 124 */ 125 Query<T> asOf(Timestamp asOf); 126 127 /** 128 * Execute the query against the draft set of tables. 129 */ 130 Query<T> asDraft(); 131 132 /** 133 * Convert the query to a DTO bean query. 134 * <p> 135 * We effectively use the underlying ORM query to build the SQL and then execute 136 * and map it into DTO beans. 137 */ 138 <D> DtoQuery<D> asDto(Class<D> dtoClass); 139 140 /** 141 * Return the underlying query as an UpdateQuery. 142 * <p> 143 * Typically this is used with query beans to covert a query bean 144 * query into an UpdateQuery like the examples below. 145 * </p> 146 * 147 * <pre>{@code 148 * 149 * int rowsUpdated = new QCustomer() 150 * .name.startsWith("Rob") 151 * .asUpdate() 152 * .set("active", false) 153 * .update();; 154 * 155 * }</pre> 156 * 157 * <pre>{@code 158 * 159 * int rowsUpdated = new QContact() 160 * .notes.note.startsWith("Make Inactive") 161 * .email.endsWith("@foo.com") 162 * .customer.id.equalTo(42) 163 * .asUpdate() 164 * .set("inactive", true) 165 * .setRaw("email = lower(email)") 166 * .update(); 167 * 168 * }</pre> 169 */ 170 UpdateQuery<T> asUpdate(); 171 172 /** 173 * Execute the query with the given lock type and WAIT. 174 * <p> 175 * Note that <code>forUpdate()</code> is the same as 176 * <code>withLock(LockType.UPDATE)</code>. 177 * <p> 178 * Provides us with the ability to explicitly use Postgres 179 * SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks. 180 */ 181 Query<T> withLock(Query.LockType lockType); 182 183 /** 184 * Execute the query with the given lock type and lock wait. 185 * <p> 186 * Note that <code>forUpdateNoWait()</code> is the same as 187 * <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>. 188 * <p> 189 * Provides us with the ability to explicitly use Postgres 190 * SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks. 191 */ 192 Query<T> withLock(Query.LockType lockType, Query.LockWait lockWait); 193 194 /** 195 * Execute using "for update" clause which results in the DB locking the record. 196 */ 197 Query<T> forUpdate(); 198 199 /** 200 * Deprecated - migrate to withLock(). 201 * Execute using "for update" with given lock type (currently Postgres only). 202 */ 203 @Deprecated 204 Query<T> forUpdate(Query.LockType lockType); 205 206 /** 207 * Execute using "for update" clause with No Wait option. 208 * <p> 209 * This is typically a Postgres and Oracle only option at this stage. 210 * </p> 211 */ 212 Query<T> forUpdateNoWait(); 213 214 /** 215 * Deprecated - migrate to withLock(). 216 * Execute using "for update nowait" with given lock type (currently Postgres only). 217 */ 218 @Deprecated 219 Query<T> forUpdateNoWait(Query.LockType lockType); 220 221 /** 222 * Execute using "for update" clause with Skip Locked option. 223 * <p> 224 * This is typically a Postgres and Oracle only option at this stage. 225 * </p> 226 */ 227 Query<T> forUpdateSkipLocked(); 228 229 /** 230 * Deprecated - migrate to withLock(). 231 * Execute using "for update skip locked" with given lock type (currently Postgres only). 232 */ 233 @Deprecated 234 Query<T> forUpdateSkipLocked(Query.LockType lockType); 235 236 /** 237 * Execute the query including soft deleted rows. 238 */ 239 Query<T> setIncludeSoftDeletes(); 240 241 /** 242 * Execute the query using the given transaction. 243 */ 244 Query<T> usingTransaction(Transaction transaction); 245 246 /** 247 * Execute the query using the given connection. 248 */ 249 Query<T> usingConnection(Connection connection); 250 251 /** 252 * Execute as a delete query deleting the 'root level' beans that match the predicates 253 * in the query. 254 * <p> 255 * Note that if the query includes joins then the generated delete statement may not be 256 * optimal depending on the database platform. 257 * </p> 258 * 259 * @return the number of rows that were deleted. 260 */ 261 int delete(); 262 263 /** 264 * Execute as a delete query deleting the 'root level' beans that match the predicates 265 * in the query. 266 * <p> 267 * Note that if the query includes joins then the generated delete statement may not be 268 * optimal depending on the database platform. 269 * </p> 270 * 271 * @return the number of rows that were deleted. 272 */ 273 int delete(Transaction transaction); 274 275 /** 276 * Execute as a update query. 277 * 278 * @return the number of rows that were updated. 279 * @see UpdateQuery 280 */ 281 int update(); 282 283 /** 284 * Execute as a update query with the given transaction. 285 * 286 * @return the number of rows that were updated. 287 * @see UpdateQuery 288 */ 289 int update(Transaction transaction); 290 291 /** 292 * Execute the query returning true if a row is found. 293 * <p> 294 * The query is executed using max rows of 1 and will only select the id property. 295 * This method is really just a convenient way to optimise a query to perform a 296 * 'does a row exist in the db' check. 297 * </p> 298 * 299 * <h2>Example:</h2> 300 * <pre>{@code 301 * 302 * boolean userExists = query().where().eq("email", "rob@foo.com").exists(); 303 * 304 * }</pre> 305 * 306 * <h2>Example using a query bean:</h2> 307 * <pre>{@code 308 * 309 * boolean userExists = new QContact().email.equalTo("rob@foo.com").exists(); 310 * 311 * }</pre> 312 * 313 * @return True if the query finds a matching row in the database 314 */ 315 boolean exists(); 316 317 /** 318 * Execute the query iterating over the results. 319 * 320 * @see Query#findIterate() 321 */ 322 QueryIterator<T> findIterate(); 323 324 /** 325 * Execute the query process the beans one at a time. 326 * 327 * @see Query#findEach(Consumer) 328 */ 329 void findEach(Consumer<T> consumer); 330 331 /** 332 * Execute the query processing the beans one at a time with the ability to 333 * stop processing before reading all the beans. 334 * 335 * @see Query#findEachWhile(Predicate) 336 */ 337 void findEachWhile(Predicate<T> consumer); 338 339 /** 340 * Execute the query returning a list. 341 * 342 * @see Query#findList() 343 */ 344 @Nonnull 345 List<T> findList(); 346 347 /** 348 * Execute the query returning the list of Id's. 349 * 350 * @see Query#findIds() 351 */ 352 @Nonnull 353 <A> List<A> findIds(); 354 355 /** 356 * Return the count of entities this query should return. 357 * <p> 358 * This is the number of 'top level' or 'root level' entities. 359 * </p> 360 */ 361 int findCount(); 362 363 /** 364 * Execute the query returning a set. 365 * 366 * @see Query#findSet() 367 */ 368 @Nonnull 369 Set<T> findSet(); 370 371 /** 372 * Execute the query returning a map. 373 * 374 * @see Query#findMap() 375 */ 376 @Nonnull 377 <K> Map<K, T> findMap(); 378 379 /** 380 * Execute the query returning a list of values for a single property. 381 * 382 * <h3>Example 1:</h3> 383 * <pre>{@code 384 * 385 * List<String> names = 386 * DB.find(Customer.class) 387 * .select("name") 388 * .order().asc("name") 389 * .findSingleAttributeList(); 390 * 391 * }</pre> 392 * 393 * <h3>Example 2:</h3> 394 * <pre>{@code 395 * 396 * List<String> names = 397 * DB.find(Customer.class) 398 * .setDistinct(true) 399 * .select("name") 400 * .where().eq("status", Customer.Status.NEW) 401 * .order().asc("name") 402 * .setMaxRows(100) 403 * .findSingleAttributeList(); 404 * 405 * }</pre> 406 * 407 * @return the list of values for the selected property 408 */ 409 @Nonnull 410 <A> List<A> findSingleAttributeList(); 411 412 /** 413 * Execute a query returning a single value of a single property/column. 414 * <pre>{@code 415 * 416 * String name = 417 * DB.find(Customer.class) 418 * .select("name") 419 * .where().eq("id", 42) 420 * .findSingleAttribute(); 421 * 422 * }</pre> 423 */ 424 default <A> A findSingleAttribute() { 425 List<A> list = findSingleAttributeList(); 426 return !list.isEmpty() ? list.get(0) : null; 427 } 428 429 /** 430 * Execute the query returning a single bean or null (if no matching 431 * bean is found). 432 * <p> 433 * If more than 1 row is found for this query then a NonUniqueResultException is 434 * thrown. 435 * </p> 436 * 437 * @throws NonUniqueResultException if more than one result was found 438 * @see Query#findOne() 439 */ 440 @Nullable 441 T findOne(); 442 443 /** 444 * Execute the query returning an optional bean. 445 */ 446 @Nonnull 447 Optional<T> findOneOrEmpty(); 448 449 /** 450 * Execute find row count query in a background thread. 451 * <p> 452 * This returns a Future object which can be used to cancel, check the 453 * execution status (isDone etc) and get the value (with or without a 454 * timeout). 455 * </p> 456 * 457 * @return a Future object for the row count query 458 */ 459 @Nonnull 460 FutureRowCount<T> findFutureCount(); 461 462 /** 463 * Execute find Id's query in a background thread. 464 * <p> 465 * This returns a Future object which can be used to cancel, check the 466 * execution status (isDone etc) and get the value (with or without a 467 * timeout). 468 * </p> 469 * 470 * @return a Future object for the list of Id's 471 */ 472 @Nonnull 473 FutureIds<T> findFutureIds(); 474 475 /** 476 * Execute find list query in a background thread. 477 * <p> 478 * This returns a Future object which can be used to cancel, check the 479 * execution status (isDone etc) and get the value (with or without a 480 * timeout). 481 * </p> 482 * 483 * @return a Future object for the list result of the query 484 */ 485 @Nonnull 486 FutureList<T> findFutureList(); 487 488 /** 489 * Return a PagedList for this query using firstRow and maxRows. 490 * <p> 491 * The benefit of using this over findList() is that it provides functionality to get the 492 * total row count etc. 493 * </p> 494 * <p> 495 * If maxRows is not set on the query prior to calling findPagedList() then a 496 * PersistenceException is thrown. 497 * </p> 498 * <pre>{@code 499 * 500 * PagedList<Order> pagedList = DB.find(Order.class) 501 * .setFirstRow(50) 502 * .setMaxRows(20) 503 * .findPagedList(); 504 * 505 * // fetch the total row count in the background 506 * pagedList.loadRowCount(); 507 * 508 * List<Order> orders = pagedList.getList(); 509 * int totalRowCount = pagedList.getTotalRowCount(); 510 * 511 * }</pre> 512 * 513 * @return The PagedList 514 * @see Query#findPagedList() 515 */ 516 @Nonnull 517 PagedList<T> findPagedList(); 518 519 /** 520 * Return versions of a @History entity bean. 521 * <p> 522 * Generally this query is expected to be a find by id or unique predicates query. 523 * It will execute the query against the history returning the versions of the bean. 524 * </p> 525 */ 526 @Nonnull 527 List<Version<T>> findVersions(); 528 529 /** 530 * Return versions of a @History entity bean between the 2 timestamps. 531 * <p> 532 * Generally this query is expected to be a find by id or unique predicates query. 533 * It will execute the query against the history returning the versions of the bean. 534 * </p> 535 */ 536 @Nonnull 537 List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end); 538 539 /** 540 * Add some filter predicate expressions to the many property. 541 */ 542 @Nonnull 543 ExpressionList<T> filterMany(String manyProperty); 544 545 /** 546 * Add filter expressions to the many property. 547 * 548 * <pre>{@code 549 * 550 * DB.find(Customer.class) 551 * .where() 552 * .eq("name", "Rob") 553 * .filterMany("orders", "status = ?", Status.NEW) 554 * .findList(); 555 * 556 * }</pre> 557 * 558 * @param manyProperty The many property 559 * @param expressions Filter expressions with and, or and ? or ?1 type bind parameters 560 * @param params Bind parameters used in the expressions 561 */ 562 ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params); 563 564 /** 565 * Specify specific properties to fetch on the main/root bean (aka partial 566 * object). 567 * 568 * @see Query#select(String) 569 */ 570 Query<T> select(String properties); 571 572 /** 573 * Apply the fetchGroup which defines what part of the object graph to load. 574 */ 575 Query<T> select(FetchGroup<T> fetchGroup); 576 577 /** 578 * Set whether this query uses DISTINCT. 579 * <p> 580 * The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that 581 * generally ORM queries include the "id" property and this doesn't make sense for distinct queries. 582 * </p> 583 * <pre>{@code 584 * 585 * List<Customer> customers = 586 * DB.find(Customer.class) 587 * .setDistinct(true) 588 * .select("name") // only select the customer name 589 * .findList(); 590 * 591 * }</pre> 592 */ 593 Query<T> setDistinct(boolean distinct); 594 595 /** 596 * Set the index(es) to search for a document store which uses partitions. 597 * <p> 598 * For example, when executing a query against ElasticSearch with daily indexes we can 599 * explicitly specify the indexes to search against. 600 * </p> 601 * 602 * @param indexName The index or indexes to search against 603 * @return This query 604 * @see Query#setDocIndexName(String) 605 */ 606 Query<T> setDocIndexName(String indexName); 607 608 /** 609 * Set the first row to fetch. 610 * 611 * @see Query#setFirstRow(int) 612 */ 613 ExpressionList<T> setFirstRow(int firstRow); 614 615 /** 616 * Set the maximum number of rows to fetch. 617 * 618 * @see Query#setMaxRows(int) 619 */ 620 ExpressionList<T> setMaxRows(int maxRows); 621 622 /** 623 * Set the name of the property which values become the key of a map. 624 * 625 * @see Query#setMapKey(String) 626 */ 627 Query<T> setMapKey(String mapKey); 628 629 /** 630 * Set to true when this query should use the bean cache. 631 * <p> 632 * This is now the same as setUseBeanCache(CacheMode.ON) and will be deprecated. 633 * </p> 634 * 635 * @see Query#setUseCache(boolean) 636 */ 637 Query<T> setUseCache(boolean useCache); 638 639 /** 640 * Set the mode to use the bean cache when executing this query. 641 * 642 * @see Query#setBeanCacheMode(CacheMode) 643 */ 644 Query<T> setBeanCacheMode(CacheMode beanCacheMode); 645 646 /** 647 * Set the {@link CacheMode} to use the query cache for executing this query. 648 * 649 * @see Query#setUseQueryCache(boolean) 650 */ 651 Query<T> setUseQueryCache(CacheMode useCache); 652 653 /** 654 * Extended version for setDistinct in conjunction with "findSingleAttributeList"; 655 * <pre>{@code 656 * 657 * List<CountedValue<Order.Status>> orderStatusCount = 658 * 659 * DB.find(Order.class) 660 * .select("status") 661 * .where() 662 * .gt("orderDate", LocalDate.now().minusMonths(3)) 663 * 664 * // fetch as single attribute with a COUNT 665 * .setCountDistinct(CountDistinctOrder.COUNT_DESC_ATTR_ASC) 666 * .findSingleAttributeList(); 667 * 668 * for (CountedValue<Order.Status> entry : orderStatusCount) { 669 * System.out.println(" count:" + entry.getCount()+" orderStatus:" + entry.getValue() ); 670 * } 671 * 672 * // produces 673 * 674 * count:3 orderStatus:NEW 675 * count:1 orderStatus:SHIPPED 676 * count:1 orderStatus:COMPLETE 677 * 678 * }</pre> 679 */ 680 Query<T> setCountDistinct(CountDistinctOrder orderBy); 681 682 /** 683 * Calls {@link #setUseQueryCache(CacheMode)} with <code>ON</code> or <code>OFF</code>. 684 * 685 * @see Query#setUseQueryCache(CacheMode) 686 */ 687 default Query<T> setUseQueryCache(boolean enabled) { 688 return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF); 689 } 690 691 /** 692 * Set to true if this query should execute against the doc store. 693 * <p> 694 * When setting this you may also consider disabling lazy loading. 695 * </p> 696 */ 697 Query<T> setUseDocStore(boolean useDocsStore); 698 699 /** 700 * Set true if you want to disable lazy loading. 701 * <p> 702 * That is, once the object graph is returned further lazy loading is disabled. 703 * </p> 704 */ 705 Query<T> setDisableLazyLoading(boolean disableLazyLoading); 706 707 /** 708 * Disable read auditing for this query. 709 * <p> 710 * This is intended to be used when the query is not a user initiated query and instead 711 * part of the internal processing in an application to load a cache or document store etc. 712 * In these cases we don't want the query to be part of read auditing. 713 * </p> 714 */ 715 Query<T> setDisableReadAuditing(); 716 717 /** 718 * Set a label on the query (to help identify query execution statistics). 719 */ 720 Query<T> setLabel(String label); 721 722 /** 723 * Add expressions to the having clause. 724 * <p> 725 * The having clause is only used for queries based on raw sql (via SqlSelect 726 * annotation etc). 727 * </p> 728 */ 729 ExpressionList<T> having(); 730 731 /** 732 * Add another expression to the where clause. 733 */ 734 ExpressionList<T> where(); 735 736 /** 737 * Add the expressions to this expression list. 738 * 739 * @param expressions The expressions that are parsed and added to this expression list 740 * @param params Bind parameters to match ? or ?1 bind positions. 741 */ 742 ExpressionList<T> where(String expressions, Object... params); 743 744 /** 745 * Path exists - for the given path in a JSON document. 746 * <pre>{@code 747 * 748 * where().jsonExists("content", "path.other") 749 * 750 * }</pre> 751 * 752 * @param propertyName the property that holds a JSON document 753 * @param path the nested path in the JSON document in dot notation 754 */ 755 ExpressionList<T> jsonExists(String propertyName, String path); 756 757 /** 758 * Path does not exist - for the given path in a JSON document. 759 * <pre>{@code 760 * 761 * where().jsonNotExists("content", "path.other") 762 * 763 * }</pre> 764 * 765 * @param propertyName the property that holds a JSON document 766 * @param path the nested path in the JSON document in dot notation 767 */ 768 ExpressionList<T> jsonNotExists(String propertyName, String path); 769 770 /** 771 * Equal to expression for the value at the given path in the JSON document. 772 * <pre>{@code 773 * 774 * where().jsonEqualTo("content", "path.other", 34) 775 * 776 * }</pre> 777 * 778 * @param propertyName the property that holds a JSON document 779 * @param path the nested path in the JSON document in dot notation 780 * @param value the value used to test against the document path's value 781 */ 782 ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value); 783 784 /** 785 * Not Equal to - for the given path in a JSON document. 786 * <pre>{@code 787 * 788 * where().jsonNotEqualTo("content", "path.other", 34) 789 * 790 * }</pre> 791 * 792 * @param propertyName the property that holds a JSON document 793 * @param path the nested path in the JSON document in dot notation 794 * @param value the value used to test against the document path's value 795 */ 796 ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object value); 797 798 /** 799 * Greater than - for the given path in a JSON document. 800 * <pre>{@code 801 * 802 * where().jsonGreaterThan("content", "path.other", 34) 803 * 804 * }</pre> 805 */ 806 ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object value); 807 808 /** 809 * Greater than or equal to - for the given path in a JSON document. 810 * <pre>{@code 811 * 812 * where().jsonGreaterOrEqual("content", "path.other", 34) 813 * 814 * }</pre> 815 */ 816 ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object value); 817 818 /** 819 * Less than - for the given path in a JSON document. 820 * <pre>{@code 821 * 822 * where().jsonLessThan("content", "path.other", 34) 823 * 824 * }</pre> 825 */ 826 ExpressionList<T> jsonLessThan(String propertyName, String path, Object value); 827 828 /** 829 * Less than or equal to - for the given path in a JSON document. 830 * <pre>{@code 831 * 832 * where().jsonLessOrEqualTo("content", "path.other", 34) 833 * 834 * }</pre> 835 */ 836 ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object value); 837 838 /** 839 * Between - for the given path in a JSON document. 840 * <pre>{@code 841 * 842 * where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime) 843 * 844 * }</pre> 845 */ 846 ExpressionList<T> jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue); 847 848 /** 849 * Add an Expression to the list. 850 */ 851 ExpressionList<T> add(Expression expr); 852 853 /** 854 * Add a list of Expressions to this ExpressionList.s 855 */ 856 ExpressionList<T> addAll(ExpressionList<T> exprList); 857 858 /** 859 * Equal To - property is equal to a given value. 860 */ 861 ExpressionList<T> eq(String propertyName, Object value); 862 863 /** 864 * Equal To or Null - property is equal to a given value or null. 865 */ 866 ExpressionList<T> eqOrNull(String propertyName, Object value); 867 868 /** 869 * Not Equal To - property not equal to the given value. 870 */ 871 ExpressionList<T> ne(String propertyName, Object value); 872 873 /** 874 * Case Insensitive Equal To - property equal to the given value (typically 875 * using a lower() function to make it case insensitive). 876 */ 877 ExpressionList<T> ieq(String propertyName, String value); 878 879 /** 880 * Case Insensitive Not Equal To - property not equal to the given value (typically 881 * using a lower() function to make it case insensitive). 882 */ 883 ExpressionList<T> ine(String propertyName, String value); 884 885 /** 886 * Value in Range between 2 properties. 887 * 888 * <pre>{@code 889 * 890 * .startDate.inRangeWith(endDate, now) 891 * 892 * // which equates to 893 * startDate <= now and (endDate > now or endDate is null) 894 * 895 * }</pre> 896 * 897 * <p> 898 * This is a convenience expression combining a number of simple expressions. 899 * The most common use of this could be called "effective dating" where 2 date or 900 * timestamp columns represent the date range in which 901 */ 902 ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value); 903 904 /** 905 * In Range - {@code property >= value1 and property < value2}. 906 * <p> 907 * Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps. 908 * </p> 909 */ 910 ExpressionList<T> inRange(String propertyName, Object value1, Object value2); 911 912 /** 913 * Between - property between the two given values. 914 */ 915 ExpressionList<T> between(String propertyName, Object value1, Object value2); 916 917 /** 918 * Between - value between the two properties. 919 */ 920 ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value); 921 922 /** 923 * Greater Than - property greater than the given value. 924 */ 925 ExpressionList<T> gt(String propertyName, Object value); 926 927 /** 928 * Greater Than or Null - property greater than the given value or null. 929 */ 930 ExpressionList<T> gtOrNull(String propertyName, Object value); 931 932 /** 933 * Greater Than or Equal to OR Null - <code> >= or null </code>. 934 */ 935 ExpressionList<T> geOrNull(String propertyName, Object value); 936 937 /** 938 * Greater Than or Equal to - property greater than or equal to the given 939 * value. 940 */ 941 ExpressionList<T> ge(String propertyName, Object value); 942 943 /** 944 * Less Than - property less than the given value. 945 */ 946 ExpressionList<T> lt(String propertyName, Object value); 947 948 /** 949 * Less Than or Null - property less than the given value or null. 950 */ 951 ExpressionList<T> ltOrNull(String propertyName, Object value); 952 953 /** 954 * Less Than or Equal to OR Null - <code> <= or null </code>. 955 */ 956 ExpressionList<T> leOrNull(String propertyName, Object value); 957 958 /** 959 * Less Than or Equal to - property less than or equal to the given value. 960 */ 961 ExpressionList<T> le(String propertyName, Object value); 962 963 /** 964 * Is Null - property is null. 965 */ 966 ExpressionList<T> isNull(String propertyName); 967 968 /** 969 * Is Not Null - property is not null. 970 */ 971 ExpressionList<T> isNotNull(String propertyName); 972 973 /** 974 * A "Query By Example" type of expression. 975 * <p> 976 * Pass in an example entity and for each non-null scalar properties an 977 * expression is added. 978 * </p> 979 * <p> 980 * By Default this case sensitive, will ignore numeric zero values and will 981 * use a Like for string values (you must put in your own wildcards). 982 * </p> 983 * <p> 984 * To get control over the options you can create an ExampleExpression and set 985 * those options such as case insensitive etc. 986 * </p> 987 * <pre>{@code 988 * 989 * // create an example bean and set the properties 990 * // with the query parameters you want 991 * Customer example = new Customer(); 992 * example.setName("Rob%"); 993 * example.setNotes("%something%"); 994 * 995 * List<Customer> list = 996 * DB.find(Customer.class) 997 * .where().exampleLike(example) 998 * .findList(); 999 * 1000 * }</pre> 1001 * <p> 1002 * Similarly you can create an ExampleExpression 1003 * </p> 1004 * <pre>{@code 1005 * 1006 * Customer example = new Customer(); 1007 * example.setName("Rob%"); 1008 * example.setNotes("%something%"); 1009 * 1010 * // create a ExampleExpression with more control 1011 * ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros(); 1012 * 1013 * List<Customer> list = DB.find(Customer.class).where().add(qbe).findList(); 1014 * 1015 * }</pre> 1016 */ 1017 ExpressionList<T> exampleLike(Object example); 1018 1019 /** 1020 * Case insensitive version of {@link #exampleLike(Object)} 1021 */ 1022 ExpressionList<T> iexampleLike(Object example); 1023 1024 /** 1025 * Like - property like value where the value contains the SQL wild card 1026 * characters % (percentage) and _ (underscore). 1027 */ 1028 ExpressionList<T> like(String propertyName, String value); 1029 1030 /** 1031 * Case insensitive Like - property like value where the value contains the 1032 * SQL wild card characters % (percentage) and _ (underscore). Typically uses 1033 * a lower() function to make the expression case insensitive. 1034 */ 1035 ExpressionList<T> ilike(String propertyName, String value); 1036 1037 /** 1038 * Starts With - property like value%. 1039 */ 1040 ExpressionList<T> startsWith(String propertyName, String value); 1041 1042 /** 1043 * Case insensitive Starts With - property like value%. Typically uses a 1044 * lower() function to make the expression case insensitive. 1045 */ 1046 ExpressionList<T> istartsWith(String propertyName, String value); 1047 1048 /** 1049 * Ends With - property like %value. 1050 */ 1051 ExpressionList<T> endsWith(String propertyName, String value); 1052 1053 /** 1054 * Case insensitive Ends With - property like %value. Typically uses a lower() 1055 * function to make the expression case insensitive. 1056 */ 1057 ExpressionList<T> iendsWith(String propertyName, String value); 1058 1059 /** 1060 * Contains - property like %value%. 1061 */ 1062 ExpressionList<T> contains(String propertyName, String value); 1063 1064 /** 1065 * Case insensitive Contains - property like %value%. Typically uses a lower() 1066 * function to make the expression case insensitive. 1067 */ 1068 ExpressionList<T> icontains(String propertyName, String value); 1069 1070 /** 1071 * In expression using pairs of value objects. 1072 */ 1073 ExpressionList<T> inPairs(Pairs pairs); 1074 1075 /** 1076 * In - using a subQuery. 1077 */ 1078 ExpressionList<T> in(String propertyName, Query<?> subQuery); 1079 1080 /** 1081 * In - property has a value in the array of values. 1082 */ 1083 ExpressionList<T> in(String propertyName, Object... values); 1084 1085 /** 1086 * In - property has a value in the collection of values. 1087 */ 1088 ExpressionList<T> in(String propertyName, Collection<?> values); 1089 1090 /** 1091 * In where null or empty values means that no predicate is added to the query. 1092 * <p> 1093 * That is, only add the IN predicate if the values are not null or empty. 1094 * <p> 1095 * Without this we typically need to code an <code>if</code> block to only add 1096 * the IN predicate if the collection is not empty like: 1097 * </p> 1098 * 1099 * <h3>Without inOrEmpty()</h3> 1100 * <pre>{@code 1101 * 1102 * query.where() // add some predicates 1103 * .eq("status", Status.NEW); 1104 * 1105 * if (ids != null && !ids.isEmpty()) { 1106 * query.where().in("customer.id", ids); 1107 * } 1108 * 1109 * query.findList(); 1110 * 1111 * }</pre> 1112 * 1113 * <h3>Using inOrEmpty()</h3> 1114 * <pre>{@code 1115 * 1116 * query.where() 1117 * .eq("status", Status.NEW) 1118 * .inOrEmpty("customer.id", ids) 1119 * .findList(); 1120 * 1121 * }</pre> 1122 */ 1123 ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values); 1124 1125 /** 1126 * In - using a subQuery. 1127 * <p> 1128 * This is exactly the same as in() and provided due to "in" being a Kotlin keyword 1129 * (and hence to avoid the slightly ugly escaping when using in() in Kotlin) 1130 */ 1131 default ExpressionList<T> isIn(String propertyName, Query<?> subQuery) { 1132 return in(propertyName, subQuery); 1133 } 1134 1135 /** 1136 * In - property has a value in the array of values. 1137 * <p> 1138 * This is exactly the same as in() and provided due to "in" being a Kotlin keyword 1139 * (and hence to avoid the slightly ugly escaping when using in() in Kotlin) 1140 */ 1141 default ExpressionList<T> isIn(String propertyName, Object... values) { 1142 return in(propertyName, values); 1143 } 1144 1145 /** 1146 * In - property has a value in the collection of values. 1147 * <p> 1148 * This is exactly the same as in() and provided due to "in" being a Kotlin keyword 1149 * (and hence to avoid the slightly ugly escaping when using in() in Kotlin) 1150 */ 1151 default ExpressionList<T> isIn(String propertyName, Collection<?> values) { 1152 return in(propertyName, values); 1153 } 1154 1155 /** 1156 * Not In - property has a value in the array of values. 1157 */ 1158 ExpressionList<T> notIn(String propertyName, Object... values); 1159 1160 /** 1161 * Not In - property has a value in the collection of values. 1162 */ 1163 ExpressionList<T> notIn(String propertyName, Collection<?> values); 1164 1165 /** 1166 * Not In - using a subQuery. 1167 */ 1168 ExpressionList<T> notIn(String propertyName, Query<?> subQuery); 1169 1170 /** 1171 * Is empty expression for collection properties. 1172 */ 1173 ExpressionList<T> isEmpty(String propertyName); 1174 1175 /** 1176 * Is not empty expression for collection properties. 1177 */ 1178 ExpressionList<T> isNotEmpty(String propertyName); 1179 1180 /** 1181 * Exists expression 1182 */ 1183 ExpressionList<T> exists(Query<?> subQuery); 1184 1185 /** 1186 * Not exists expression 1187 */ 1188 ExpressionList<T> notExists(Query<?> subQuery); 1189 1190 /** 1191 * Id IN a list of id values. 1192 */ 1193 ExpressionList<T> idIn(Object... idValues); 1194 1195 /** 1196 * Id IN a collection of id values. 1197 */ 1198 ExpressionList<T> idIn(Collection<?> idValues); 1199 1200 /** 1201 * Id Equal to - ID property is equal to the value. 1202 */ 1203 ExpressionList<T> idEq(Object value); 1204 1205 /** 1206 * All Equal - Map containing property names and their values. 1207 * <p> 1208 * Expression where all the property names in the map are equal to the 1209 * corresponding value. 1210 * </p> 1211 * 1212 * @param propertyMap a map keyed by property names. 1213 */ 1214 ExpressionList<T> allEq(Map<String, Object> propertyMap); 1215 1216 /** 1217 * Array property contains entries with the given values. 1218 */ 1219 ExpressionList<T> arrayContains(String propertyName, Object... values); 1220 1221 /** 1222 * Array does not contain the given values. 1223 * <p> 1224 * Array support is effectively limited to Postgres at this time. 1225 * </p> 1226 */ 1227 ExpressionList<T> arrayNotContains(String propertyName, Object... values); 1228 1229 /** 1230 * Array is empty - for the given array property. 1231 * <p> 1232 * Array support is effectively limited to Postgres at this time. 1233 * </p> 1234 */ 1235 ExpressionList<T> arrayIsEmpty(String propertyName); 1236 1237 /** 1238 * Array is not empty - for the given array property. 1239 * <p> 1240 * Array support is effectively limited to Postgres at this time. 1241 * </p> 1242 */ 1243 ExpressionList<T> arrayIsNotEmpty(String propertyName); 1244 1245 /** 1246 * Add expression for ANY of the given bit flags to be set. 1247 * <pre>{@code 1248 * 1249 * where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR) 1250 * 1251 * }</pre> 1252 * 1253 * @param propertyName The property that holds the flags value 1254 * @param flags The flags we are looking for 1255 */ 1256 ExpressionList<T> bitwiseAny(String propertyName, long flags); 1257 1258 /** 1259 * Add expression for ALL of the given bit flags to be set. 1260 * <pre>{@code 1261 * 1262 * where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR) 1263 * 1264 * }</pre> 1265 * 1266 * @param propertyName The property that holds the flags value 1267 * @param flags The flags we are looking for 1268 */ 1269 ExpressionList<T> bitwiseAll(String propertyName, long flags); 1270 1271 /** 1272 * Add expression for the given bit flags to be NOT set. 1273 * <pre>{@code 1274 * 1275 * where().bitwiseNot("flags", BwFlags.HAS_COLOUR) 1276 * 1277 * }</pre> 1278 * 1279 * @param propertyName The property that holds the flags value 1280 * @param flags The flags we are looking for 1281 */ 1282 ExpressionList<T> bitwiseNot(String propertyName, long flags); 1283 1284 /** 1285 * Add bitwise AND expression of the given bit flags to compare with the match/mask. 1286 * <p> 1287 * <pre>{@code 1288 * 1289 * // Flags Bulk + Size = Size 1290 * // ... meaning Bulk is not set and Size is set 1291 * 1292 * long selectedFlags = BwFlags.HAS_BULK + BwFlags.HAS_SIZE; 1293 * long mask = BwFlags.HAS_SIZE; // Only Size flag set 1294 * 1295 * where().bitwiseAnd("flags", selectedFlags, mask) 1296 * 1297 * }</pre> 1298 * 1299 * @param propertyName The property that holds the flags value 1300 * @param flags The flags we are looking for 1301 */ 1302 ExpressionList<T> bitwiseAnd(String propertyName, long flags, long match); 1303 1304 /** 1305 * Add raw expression with a single parameter. 1306 * <p> 1307 * The raw expression should contain a single ? or ?1 1308 * at the location of the parameter. We use ?1 when binding a 1309 * collection for an IN expression. 1310 * <p> 1311 * When properties in the clause are fully qualified as table-column names 1312 * then they are not translated. logical property name names (not fully 1313 * qualified) will still be translated to their physical name. 1314 * <p> 1315 * <h4>Examples:</h4> 1316 * <pre>{@code 1317 * 1318 * // use a database function 1319 * raw("add_days(orderDate, 10) < ?", someDate) 1320 * 1321 * raw("name like ?", "Rob%") 1322 * 1323 * raw("name in (?1)", asList("Rob", "Fiona", "Jack")) 1324 * 1325 * raw("name = any(?)", asList("Rob", "Fiona", "Jack")) 1326 * 1327 * }</pre> 1328 * 1329 * <h4>Subquery examples:</h4> 1330 * <pre>{@code 1331 * 1332 * // Bind collection using ?1 1333 * .raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack")) 1334 * 1335 * // Using Postgres ANY expression 1336 * .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds) 1337 * 1338 * }</pre> 1339 */ 1340 ExpressionList<T> raw(String raw, Object value); 1341 1342 /** 1343 * Add raw expression with an array of parameters. 1344 * <p> 1345 * The raw expression should contain the same number of ? or ?1, ?2 ... bind parameters 1346 * as there are values. We use ?1, ?2 etc when binding a collection for an IN expression. 1347 * <p> 1348 * When properties in the clause are fully qualified as table-column names 1349 * then they are not translated. logical property name names (not fully 1350 * qualified) will still be translated to their physical name. 1351 * </p> 1352 * 1353 * <h4>Examples:</h4> 1354 * <pre>{@code 1355 * 1356 * raw("unitPrice > ? and product.id > ?", 2, 3) 1357 * 1358 * raw("(status = ? or (orderDate < ? and shipDate is null) or customer.name like ?)", 1359 * Order.Status.APPROVED, 1360 * new Timestamp(System.currentTimeMillis()), 1361 * "Rob") 1362 * 1363 * }</pre></pre> 1364 */ 1365 ExpressionList<T> raw(String raw, Object... values); 1366 1367 /** 1368 * Add raw expression with no parameters. 1369 * <p> 1370 * When properties in the clause are fully qualified as table-column names 1371 * then they are not translated. logical property name names (not fully 1372 * qualified) will still be translated to their physical name. 1373 * </p> 1374 * <pre>{@code 1375 * 1376 * raw("orderQty < shipQty") 1377 * 1378 * }</pre> 1379 * 1380 * <h4>Subquery example:</h4> 1381 * <pre>{@code 1382 * 1383 * .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds) 1384 * 1385 * }</pre> 1386 */ 1387 ExpressionList<T> raw(String raw); 1388 1389 /** 1390 * Only add the raw expression if the values is not null or empty. 1391 * <p> 1392 * This is a pure convenience expression to make it nicer to deal with the pattern where we use 1393 * raw() expression with a subquery and only want to add the subquery predicate when the collection 1394 * of values is not empty. 1395 * </p> 1396 * <h3>Without inOrEmpty()</h3> 1397 * <pre>{@code 1398 * 1399 * query.where() // add some predicates 1400 * .eq("status", Status.NEW); 1401 * 1402 * // common pattern - we can use rawOrEmpty() instead 1403 * if (orderIds != null && !orderIds.isEmpty()) { 1404 * query.where().raw("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds); 1405 * } 1406 * 1407 * query.findList(); 1408 * 1409 * }</pre> 1410 * 1411 * <h3>Using rawOrEmpty()</h3> 1412 * Note that in the example below we use the <code>?1</code> bind parameter to get "parameter expansion" 1413 * for each element in the collection. 1414 * 1415 * <pre>{@code 1416 * 1417 * query.where() 1418 * .eq("status", Status.NEW) 1419 * // only add the expression if orderIds is not empty 1420 * .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds); 1421 * .findList(); 1422 * 1423 * }</pre> 1424 * 1425 * <h3>Postgres ANY</h3> 1426 * With Postgres we would often use the SQL <code>ANY</code> expression and array parameter binding 1427 * rather than <code>IN</code>. 1428 * 1429 * <pre>{@code 1430 * 1431 * query.where() 1432 * .eq("status", Status.NEW) 1433 * .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id = any(?))", orderIds); 1434 * .findList(); 1435 * 1436 * }</pre> 1437 * <p> 1438 * Note that we need to cast the Postgres array for UUID types like: 1439 * </p> 1440 * <pre>{@code 1441 * 1442 * " ... = any(?::uuid[])" 1443 * 1444 * }</pre> 1445 * 1446 * @param raw The raw expression that is typically a subquery 1447 * @param values The values which is typically a list or set of id values. 1448 */ 1449 ExpressionList<T> rawOrEmpty(String raw, Collection<?> values); 1450 1451 /** 1452 * Add a match expression. 1453 * 1454 * @param propertyName The property name for the match 1455 * @param search The search value 1456 */ 1457 ExpressionList<T> match(String propertyName, String search); 1458 1459 /** 1460 * Add a match expression with options. 1461 * 1462 * @param propertyName The property name for the match 1463 * @param search The search value 1464 */ 1465 ExpressionList<T> match(String propertyName, String search, Match options); 1466 1467 /** 1468 * Add a multi-match expression. 1469 */ 1470 ExpressionList<T> multiMatch(String search, String... properties); 1471 1472 /** 1473 * Add a multi-match expression using options. 1474 */ 1475 ExpressionList<T> multiMatch(String search, MultiMatch options); 1476 1477 /** 1478 * Add a simple query string expression. 1479 */ 1480 ExpressionList<T> textSimple(String search, TextSimple options); 1481 1482 /** 1483 * Add a query string expression. 1484 */ 1485 ExpressionList<T> textQueryString(String search, TextQueryString options); 1486 1487 /** 1488 * Add common terms expression. 1489 */ 1490 ExpressionList<T> textCommonTerms(String search, TextCommonTerms options); 1491 1492 /** 1493 * And - join two expressions with a logical and. 1494 */ 1495 ExpressionList<T> and(Expression expOne, Expression expTwo); 1496 1497 /** 1498 * Or - join two expressions with a logical or. 1499 */ 1500 ExpressionList<T> or(Expression expOne, Expression expTwo); 1501 1502 /** 1503 * Negate the expression (prefix it with NOT). 1504 */ 1505 ExpressionList<T> not(Expression exp); 1506 1507 /** 1508 * Start a list of expressions that will be joined by AND's 1509 * returning the expression list the expressions are added to. 1510 * <p> 1511 * This is exactly the same as conjunction(); 1512 * </p> 1513 * <p> 1514 * Use endAnd() or endJunction() to end the AND junction. 1515 * </p> 1516 * <p> 1517 * Note that a where() clause defaults to an AND junction so 1518 * typically you only explicitly need to use the and() junction 1519 * when it is nested inside an or() or not() junction. 1520 * </p> 1521 * <pre>{@code 1522 * 1523 * // Example: Nested and() 1524 * 1525 * .where() 1526 * .or() 1527 * .and() // nested and 1528 * .startsWith("name", "r") 1529 * .eq("anniversary", onAfter) 1530 * .endAnd() 1531 * .and() 1532 * .eq("status", Customer.Status.ACTIVE) 1533 * .gt("id", 0) 1534 * .endAnd() 1535 * .order().asc("name") 1536 * .findList(); 1537 * }</pre> 1538 */ 1539 Junction<T> and(); 1540 1541 /** 1542 * Return a list of expressions that will be joined by OR's. 1543 * This is exactly the same as disjunction(); 1544 * <p> 1545 * Use endOr() or endJunction() to end the OR junction. 1546 * </p> 1547 * 1548 * <pre>{@code 1549 * 1550 * // Example: (status active OR anniversary is null) 1551 * 1552 * .where() 1553 * .or() 1554 * .eq("status", Customer.Status.ACTIVE) 1555 * .isNull("anniversary") 1556 * .order().asc("name") 1557 * .findList(); 1558 * 1559 * }</pre> 1560 * 1561 * <pre>{@code 1562 * 1563 * // Example: Use or() to join 1564 * // two nested and() expressions 1565 * 1566 * .where() 1567 * .or() 1568 * .and() 1569 * .startsWith("name", "r") 1570 * .eq("anniversary", onAfter) 1571 * .endAnd() 1572 * .and() 1573 * .eq("status", Customer.Status.ACTIVE) 1574 * .gt("id", 0) 1575 * .endAnd() 1576 * .order().asc("name") 1577 * .findList(); 1578 * 1579 * }</pre> 1580 */ 1581 Junction<T> or(); 1582 1583 /** 1584 * Return a list of expressions that will be wrapped by NOT. 1585 * <p> 1586 * Use endNot() or endJunction() to end expressions being added to the 1587 * NOT expression list. 1588 * </p> 1589 * 1590 * <pre>{@code 1591 * 1592 * .where() 1593 * .not() 1594 * .gt("id", 1) 1595 * .eq("anniversary", onAfter) 1596 * .endNot() 1597 * 1598 * }</pre> 1599 * 1600 * <pre>{@code 1601 * 1602 * // Example: nested not() 1603 * 1604 * .where() 1605 * .eq("status", Customer.Status.ACTIVE) 1606 * .not() 1607 * .gt("id", 1) 1608 * .eq("anniversary", onAfter) 1609 * .endNot() 1610 * .order() 1611 * .asc("name") 1612 * .findList(); 1613 * 1614 * }</pre> 1615 */ 1616 Junction<T> not(); 1617 1618 /** 1619 * Start (and return) a list of expressions that will be joined by AND's. 1620 * <p> 1621 * This is the same as and(). 1622 * </p> 1623 */ 1624 Junction<T> conjunction(); 1625 1626 /** 1627 * Start (and return) a list of expressions that will be joined by OR's. 1628 * <p> 1629 * This is the same as or(). 1630 * </p> 1631 */ 1632 Junction<T> disjunction(); 1633 1634 /** 1635 * Start a list of expressions that will be joined by MUST. 1636 * <p> 1637 * This automatically makes the query a useDocStore(true) query that 1638 * will execute against the document store (ElasticSearch etc). 1639 * </p> 1640 * <p> 1641 * This is logically similar to and(). 1642 * </p> 1643 */ 1644 Junction<T> must(); 1645 1646 /** 1647 * Start a list of expressions that will be joined by SHOULD. 1648 * <p> 1649 * This automatically makes the query a useDocStore(true) query that 1650 * will execute against the document store (ElasticSearch etc). 1651 * </p> 1652 * <p> 1653 * This is logically similar to or(). 1654 * </p> 1655 */ 1656 Junction<T> should(); 1657 1658 /** 1659 * Start a list of expressions that will be joined by MUST NOT. 1660 * <p> 1661 * This automatically makes the query a useDocStore(true) query that 1662 * will execute against the document store (ElasticSearch etc). 1663 * </p> 1664 * <p> 1665 * This is logically similar to not(). 1666 * </p> 1667 */ 1668 Junction<T> mustNot(); 1669 1670 /** 1671 * End a junction returning the parent expression list. 1672 * <p> 1673 * Ends a and(), or(), not(), must(), mustNot() or should() junction 1674 * such that you get the parent expression. 1675 * </p> 1676 * <p> 1677 * Alternatively you can always use where() to return the top level expression list. 1678 * </p> 1679 */ 1680 ExpressionList<T> endJunction(); 1681 1682 /** 1683 * End a AND junction - synonym for endJunction(). 1684 */ 1685 ExpressionList<T> endAnd(); 1686 1687 /** 1688 * End a AND junction - synonym for endJunction(). 1689 */ 1690 ExpressionList<T> endOr(); 1691 1692 /** 1693 * End a NOT junction - synonym for endJunction(). 1694 */ 1695 ExpressionList<T> endNot(); 1696 1697}