/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/aggregation/DocumentOperators.java

https://github.com/spring-projects/spring-data-mongodb · Java · 222 lines · 75 code · 28 blank · 119 comment · 0 complexity · c38d768a6448e3ee8d3caf572982e6b3 MD5 · raw file

  1. /*
  2. * Copyright 2021-2022 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * https://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.data.mongodb.core.aggregation;
  17. import java.util.Collections;
  18. import org.bson.Document;
  19. /**
  20. * Gateway to {@literal document expressions} such as {@literal $rank, $documentNumber, etc.}
  21. *
  22. * @author Christoph Strobl
  23. * @since 3.3
  24. */
  25. public class DocumentOperators {
  26. /**
  27. * Obtain the document position (including gaps) relative to others (rank).
  28. *
  29. * @return new instance of {@link Rank}.
  30. * @since 3.3
  31. */
  32. public static Rank rank() {
  33. return new Rank();
  34. }
  35. /**
  36. * Obtain the document position (without gaps) relative to others (rank).
  37. *
  38. * @return new instance of {@link DenseRank}.
  39. * @since 3.3
  40. */
  41. public static DenseRank denseRank() {
  42. return new DenseRank();
  43. }
  44. /**
  45. * Take the field referenced by given {@literal fieldReference}.
  46. *
  47. * @param fieldReference must not be {@literal null}.
  48. * @return new instance of {@link DocumentOperatorsFactory}.
  49. */
  50. public static DocumentOperatorsFactory valueOf(String fieldReference) {
  51. return new DocumentOperatorsFactory(fieldReference);
  52. }
  53. /**
  54. * Take the value resulting from the given {@link AggregationExpression}.
  55. *
  56. * @param expression must not be {@literal null}.
  57. * @return new instance of {@link DocumentOperatorsFactory}.
  58. */
  59. public static DocumentOperatorsFactory valueOf(AggregationExpression expression) {
  60. return new DocumentOperatorsFactory(expression);
  61. }
  62. /**
  63. * Obtain the current document position.
  64. *
  65. * @return new instance of {@link DocumentNumber}.
  66. * @since 3.3
  67. */
  68. public static DocumentNumber documentNumber() {
  69. return new DocumentNumber();
  70. }
  71. /**
  72. * @author Christoph Strobl
  73. */
  74. public static class DocumentOperatorsFactory {
  75. private final Object target;
  76. public DocumentOperatorsFactory(Object target) {
  77. this.target = target;
  78. }
  79. /**
  80. * Creates new {@link AggregationExpression} that applies the expression to a document at specified position
  81. * relative to the current document.
  82. *
  83. * @param by the value to add to the current position.
  84. * @return new instance of {@link Shift}.
  85. */
  86. public Shift shift(int by) {
  87. Shift shift = usesExpression() ? Shift.shift((AggregationExpression) target) : Shift.shift(target.toString());
  88. return shift.by(by);
  89. }
  90. private boolean usesExpression() {
  91. return target instanceof AggregationExpression;
  92. }
  93. }
  94. /**
  95. * {@link Rank} resolves the current document position (the rank) relative to other documents. If multiple documents
  96. * occupy the same rank, {@literal $rank} places the document with the subsequent value at a rank with a gap.
  97. *
  98. * @author Christoph Strobl
  99. * @since 3.3
  100. */
  101. public static class Rank implements AggregationExpression {
  102. @Override
  103. public Document toDocument(AggregationOperationContext context) {
  104. return new Document("$rank", new Document());
  105. }
  106. }
  107. /**
  108. * {@link DenseRank} resolves the current document position (the rank) relative to other documents. If multiple
  109. * documents occupy the same rank, {@literal $denseRank} places the document with the subsequent value at the next
  110. * rank without any gaps.
  111. *
  112. * @author Christoph Strobl
  113. * @since 3.3
  114. */
  115. public static class DenseRank implements AggregationExpression {
  116. @Override
  117. public Document toDocument(AggregationOperationContext context) {
  118. return new Document("$denseRank", new Document());
  119. }
  120. }
  121. /**
  122. * {@link DocumentNumber} resolves the current document position.
  123. *
  124. * @author Christoph Strobl
  125. * @since 3.3
  126. */
  127. public static class DocumentNumber implements AggregationExpression {
  128. @Override
  129. public Document toDocument(AggregationOperationContext context) {
  130. return new Document("$documentNumber", new Document());
  131. }
  132. }
  133. /**
  134. * Shift applies an expression to a document in a specified position relative to the current document.
  135. *
  136. * @author Christoph Strobl
  137. * @since 3.3
  138. */
  139. public static class Shift extends AbstractAggregationExpression {
  140. private Shift(Object value) {
  141. super(value);
  142. }
  143. /**
  144. * Specifies the field to evaluate and return.
  145. *
  146. * @param fieldReference must not be {@literal null}.
  147. * @return new instance of {@link Shift}.
  148. */
  149. public static Shift shift(String fieldReference) {
  150. return new Shift(Collections.singletonMap("output", Fields.field(fieldReference)));
  151. }
  152. /**
  153. * Specifies the {@link AggregationExpression expression} to evaluate and return.
  154. *
  155. * @param expression must not be {@literal null}.
  156. * @return new instance of {@link Shift}.
  157. */
  158. public static Shift shift(AggregationExpression expression) {
  159. return new Shift(Collections.singletonMap("output", expression));
  160. }
  161. /**
  162. * Shift the document position relative to the current. Use a positive value for follow up documents (eg. 1 for the
  163. * next) or a negative value for the predecessor documents (eg. -1 for the previous).
  164. *
  165. * @param shiftBy value to add to the current position.
  166. * @return new instance of {@link Shift}.
  167. */
  168. public Shift by(int shiftBy) {
  169. return new Shift(append("by", shiftBy));
  170. }
  171. /**
  172. * Define the default value if the target document is out of range.
  173. *
  174. * @param value must not be {@literal null}.
  175. * @return new instance of {@link Shift}.
  176. */
  177. public Shift defaultTo(Object value) {
  178. return new Shift(append("default", value));
  179. }
  180. /**
  181. * Define the {@link AggregationExpression expression} to evaluate if the target document is out of range.
  182. *
  183. * @param expression must not be {@literal null}.
  184. * @return new instance of {@link Shift}.
  185. */
  186. public Shift defaultToValueOf(AggregationExpression expression) {
  187. return defaultTo(expression);
  188. }
  189. @Override
  190. protected String getMongoMethod() {
  191. return "$shift";
  192. }
  193. }
  194. }