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