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