Compare commits
261 Commits
2.2.8.RELE
...
2.1.18.REL
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7e4673e29 | ||
|
|
9d694dbdd5 | ||
|
|
74179a9af9 | ||
|
|
c1c5e3bdbb | ||
|
|
24978577cc | ||
|
|
c43ae822be | ||
|
|
881a69864f | ||
|
|
dc054a793f | ||
|
|
f048fb6800 | ||
|
|
20fdb0e63c | ||
|
|
7e3ff86d36 | ||
|
|
54c9933535 | ||
|
|
1f07a3eb29 | ||
|
|
76f4328498 | ||
|
|
c572ca4e3b | ||
|
|
f1d214b87d | ||
|
|
f4854a15f9 | ||
|
|
b491d6ce81 | ||
|
|
0b482f8dcf | ||
|
|
9f1b27c305 | ||
|
|
b6e69606b1 | ||
|
|
0429ea69fa | ||
|
|
383b7031dd | ||
|
|
e8f0ed8d59 | ||
|
|
f90d30472b | ||
|
|
cec1c8305a | ||
|
|
cd714b1ba8 | ||
|
|
0a83eec8b2 | ||
|
|
3a28fb18f6 | ||
|
|
6e65d2fd1d | ||
|
|
8d63c10e07 | ||
|
|
aee5f71229 | ||
|
|
5cc044b72c | ||
|
|
45243468ec | ||
|
|
5a162bdbaf | ||
|
|
1d15eaf42e | ||
|
|
0076e294ae | ||
|
|
cd8603caa3 | ||
|
|
aac1c3406b | ||
|
|
3a16cc80c5 | ||
|
|
c2ba361d24 | ||
|
|
eb5a331822 | ||
|
|
3100e0db01 | ||
|
|
4efaed4741 | ||
|
|
00bbf439c0 | ||
|
|
87476f9a91 | ||
|
|
7bcf686b40 | ||
|
|
8e51d005d5 | ||
|
|
1940a5c2c2 | ||
|
|
5a274029d7 | ||
|
|
c342bf266e | ||
|
|
11baf455d2 | ||
|
|
05882813ac | ||
|
|
bd3f26c928 | ||
|
|
5555aa970b | ||
|
|
e74fe05abd | ||
|
|
d579254fbc | ||
|
|
71c8e4cc02 | ||
|
|
a087c7d17c | ||
|
|
90cec275a6 | ||
|
|
e4eefe577d | ||
|
|
b57a6612f6 | ||
|
|
62b2d54e0d | ||
|
|
aff823da57 | ||
|
|
d45b630724 | ||
|
|
fc8c97aeb0 | ||
|
|
004e7f01b2 | ||
|
|
5c80ee0087 | ||
|
|
adb9dc29a2 | ||
|
|
6eb6feadbb | ||
|
|
166aab39c4 | ||
|
|
fa94c22c2a | ||
|
|
e0f88a8b84 | ||
|
|
59aa8051d3 | ||
|
|
205a06e79a | ||
|
|
899b43a29b | ||
|
|
0f0a4ed31b | ||
|
|
9acc8d5268 | ||
|
|
313ffb5426 | ||
|
|
dc859953f4 | ||
|
|
bc29f2b24e | ||
|
|
686cdac73f | ||
|
|
b7b339577b | ||
|
|
2166a6e953 | ||
|
|
3c601a699a | ||
|
|
37211fc6d7 | ||
|
|
a45c9040c4 | ||
|
|
23c0a07b93 | ||
|
|
f3a7d6a20e | ||
|
|
0d22d831f8 | ||
|
|
6b0e2ab5de | ||
|
|
5d02b84856 | ||
|
|
93e911985e | ||
|
|
e7faa1a1ec | ||
|
|
631714941a | ||
|
|
db9428cebe | ||
|
|
4be53ac952 | ||
|
|
564acd75d5 | ||
|
|
95ccdf4c20 | ||
|
|
291ef4bb75 | ||
|
|
c7461928f4 | ||
|
|
f5a5d3e96b | ||
|
|
b213aada80 | ||
|
|
403e5043cb | ||
|
|
bdbda459c0 | ||
|
|
0bf6d5f7fa | ||
|
|
f2ae14206a | ||
|
|
049159374d | ||
|
|
79f8e06fc1 | ||
|
|
370db2dce5 | ||
|
|
74325d5193 | ||
|
|
e6ea2e1379 | ||
|
|
cb85f3cfa6 | ||
|
|
aff8b89006 | ||
|
|
0ad8857368 | ||
|
|
46de82fe0b | ||
|
|
387348b615 | ||
|
|
8fd41faac6 | ||
|
|
8a15e1086b | ||
|
|
8502786648 | ||
|
|
d7107d49bf | ||
|
|
f42cb1e2f0 | ||
|
|
a9403b526f | ||
|
|
5f6291ed32 | ||
|
|
676ee80434 | ||
|
|
b54641ff86 | ||
|
|
6930c720ca | ||
|
|
611cfe9c11 | ||
|
|
507a1fbf34 | ||
|
|
087649de35 | ||
|
|
1f01f34377 | ||
|
|
295c43c6ff | ||
|
|
5a62d449bf | ||
|
|
1cbbe692b5 | ||
|
|
5bfe125160 | ||
|
|
1b6722324e | ||
|
|
a212f5f79d | ||
|
|
2879348d4b | ||
|
|
10097311c7 | ||
|
|
b8303a56b6 | ||
|
|
f9e468aebb | ||
|
|
b900dc6c09 | ||
|
|
bede55714c | ||
|
|
3ec426352f | ||
|
|
c6293e0ebd | ||
|
|
74e49a2326 | ||
|
|
69c451f69f | ||
|
|
9af8160e05 | ||
|
|
fdf4ea1e60 | ||
|
|
8c7afe012f | ||
|
|
6ba258a1f3 | ||
|
|
059c8cf1dd | ||
|
|
2b8955f583 | ||
|
|
23fde167f6 | ||
|
|
9470f82e9b | ||
|
|
1e88e241d4 | ||
|
|
0b8396c43c | ||
|
|
b602e4cb26 | ||
|
|
500393e596 | ||
|
|
7e4cbdb8b0 | ||
|
|
1d6d8ff8e6 | ||
|
|
8ea4cbe9ea | ||
|
|
45a0c36184 | ||
|
|
599c79bce2 | ||
|
|
eda6d40aa7 | ||
|
|
22b844c87f | ||
|
|
bdf7ec7c9b | ||
|
|
13db06d345 | ||
|
|
365ecd53c4 | ||
|
|
dc40c42815 | ||
|
|
49415efb8c | ||
|
|
dc234906f4 | ||
|
|
a7f51a7c85 | ||
|
|
9b0bd11d09 | ||
|
|
d7ad883f69 | ||
|
|
44308bfbe1 | ||
|
|
9b673d342f | ||
|
|
5517198310 | ||
|
|
819a04f3db | ||
|
|
f7202067a5 | ||
|
|
f20a0f20c9 | ||
|
|
02216d5941 | ||
|
|
79f2094322 | ||
|
|
afbc5cfa25 | ||
|
|
a3882a5e5c | ||
|
|
8194772388 | ||
|
|
12f18850dc | ||
|
|
816c1da248 | ||
|
|
5a78f19781 | ||
|
|
698837921b | ||
|
|
0f7fc7880b | ||
|
|
6e42f49b08 | ||
|
|
bdfe4e99ed | ||
|
|
85aa3927a6 | ||
|
|
33c4e4294f | ||
|
|
a89ab387cc | ||
|
|
e52b8c9d38 | ||
|
|
4dbf4795db | ||
|
|
8e4c6f68ae | ||
|
|
fddbd126ea | ||
|
|
ee5b26ab1c | ||
|
|
01e9a2ed67 | ||
|
|
10107c7b81 | ||
|
|
abe7876086 | ||
|
|
a759dff5fd | ||
|
|
9f8d081ef3 | ||
|
|
b8f6030441 | ||
|
|
267decf189 | ||
|
|
3a7492c68d | ||
|
|
273088b6a8 | ||
|
|
723b481f82 | ||
|
|
8a34bc46a2 | ||
|
|
bb4c16f4cd | ||
|
|
cf5b7c9763 | ||
|
|
f4414e98a2 | ||
|
|
a97bfd2a37 | ||
|
|
9fe0f5c984 | ||
|
|
718a7ffe8c | ||
|
|
f7106dc425 | ||
|
|
0698f8bcb8 | ||
|
|
3effd9ae6f | ||
|
|
7002cd1456 | ||
|
|
a15d488657 | ||
|
|
44651581b1 | ||
|
|
6d64f5b2b2 | ||
|
|
0c52a29ba8 | ||
|
|
bd8bd4f568 | ||
|
|
c75f29dc42 | ||
|
|
e493af7266 | ||
|
|
8d892e5924 | ||
|
|
053299f243 | ||
|
|
872659cc00 | ||
|
|
96978a6194 | ||
|
|
2253d3e301 | ||
|
|
5982ee84f7 | ||
|
|
dd2af6462d | ||
|
|
622643bf24 | ||
|
|
51cc55baac | ||
|
|
0b106e5649 | ||
|
|
8975d93ab3 | ||
|
|
e25b6c49f5 | ||
|
|
7a70c205de | ||
|
|
6045efa450 | ||
|
|
7b0816b3ee | ||
|
|
14e4ea736d | ||
|
|
32e7d9ab7f | ||
|
|
7f35ad9e45 | ||
|
|
60228f6e5a | ||
|
|
7604492b7f | ||
|
|
4680fe0e77 | ||
|
|
b4228c88d3 | ||
|
|
f6ef8c94c8 | ||
|
|
0d0dafa85e | ||
|
|
29aa34619f | ||
|
|
7f19f769c4 | ||
|
|
a40e89d90a | ||
|
|
6b2350200a | ||
|
|
fb50b0f6e7 | ||
|
|
ab568229b5 | ||
|
|
7f9c1bd774 | ||
|
|
670a0978da |
314
Jenkinsfile
vendored
314
Jenkinsfile
vendored
@@ -1,219 +1,123 @@
|
||||
pipeline {
|
||||
agent none
|
||||
agent none
|
||||
|
||||
triggers {
|
||||
pollSCM 'H/10 * * * *'
|
||||
upstream(upstreamProjects: "spring-data-commons/2.2.x", threshold: hudson.model.Result.SUCCESS)
|
||||
}
|
||||
triggers {
|
||||
pollSCM 'H/10 * * * *'
|
||||
upstream(upstreamProjects: "spring-data-commons/2.1.x", threshold: hudson.model.Result.SUCCESS)
|
||||
}
|
||||
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
buildDiscarder(logRotator(numToKeepStr: '14'))
|
||||
}
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
buildDiscarder(logRotator(numToKeepStr: '14'))
|
||||
}
|
||||
|
||||
stages {
|
||||
stage("Docker images") {
|
||||
parallel {
|
||||
stage('Publish JDK 8 + MongoDB 4.0') {
|
||||
when {
|
||||
changeset "ci/openjdk8-mongodb-4.0/**"
|
||||
}
|
||||
agent { label 'data' }
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
steps {
|
||||
script {
|
||||
def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.0", "ci/openjdk8-mongodb-4.0/")
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
image.push()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Publish JDK 8 + MongoDB 4.1') {
|
||||
when {
|
||||
changeset "ci/openjdk8-mongodb-4.1/**"
|
||||
}
|
||||
agent { label 'data' }
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
steps {
|
||||
script {
|
||||
def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.1", "ci/openjdk8-mongodb-4.1/")
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
image.push()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Publish JDK 8 + MongoDB 4.2') {
|
||||
when {
|
||||
changeset "ci/openjdk8-mongodb-4.2/**"
|
||||
}
|
||||
agent { label 'data' }
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
|
||||
steps {
|
||||
script {
|
||||
def image = docker.build("springci/spring-data-openjdk8-with-mongodb-4.2", "ci/openjdk8-mongodb-4.2/")
|
||||
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
|
||||
image.push()
|
||||
}
|
||||
}
|
||||
}
|
||||
stages {
|
||||
stage("Test") {
|
||||
when {
|
||||
anyOf {
|
||||
branch '2.1.x'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
parallel {
|
||||
stage("test: baseline") {
|
||||
agent {
|
||||
docker {
|
||||
image 'springci/spring-data-openjdk8-with-mongodb-4.0:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
steps {
|
||||
sh 'rm -rf ?'
|
||||
sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log'
|
||||
sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &'
|
||||
sh 'sleep 10'
|
||||
sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"'
|
||||
sh 'sleep 15'
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("test: baseline") {
|
||||
when {
|
||||
anyOf {
|
||||
branch '2.2.x'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'springci/spring-data-openjdk8-with-mongodb-4.2:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
steps {
|
||||
sh 'rm -rf ?'
|
||||
sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log'
|
||||
sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &'
|
||||
sh 'sleep 10'
|
||||
sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"'
|
||||
sh 'sleep 15'
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("Test other configurations") {
|
||||
when {
|
||||
anyOf {
|
||||
branch '2.2.x'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
parallel {
|
||||
stage("test: mongodb 4.0") {
|
||||
agent {
|
||||
docker {
|
||||
image 'springci/spring-data-openjdk8-with-mongodb-4.0:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
steps {
|
||||
sh 'rm -rf ?'
|
||||
sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log'
|
||||
sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &'
|
||||
sh 'sleep 10'
|
||||
sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"'
|
||||
sh 'sleep 15'
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B'
|
||||
}
|
||||
}
|
||||
stage("test: mongodb 4.1") {
|
||||
agent {
|
||||
docker {
|
||||
image 'springci/spring-data-openjdk8-with-mongodb-4.1:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 30, unit: 'MINUTES') }
|
||||
steps {
|
||||
sh 'rm -rf ?'
|
||||
sh 'mkdir -p /tmp/mongodb/db /tmp/mongodb/log'
|
||||
sh 'mongod --dbpath /tmp/mongodb/db --replSet rs0 --fork --logpath /tmp/mongodb/log/mongod.log &'
|
||||
sh 'sleep 10'
|
||||
sh 'mongo --eval "rs.initiate({_id: \'rs0\', members:[{_id: 0, host: \'127.0.0.1:27017\'}]});"'
|
||||
sh 'sleep 15'
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw clean dependency:list test -Dsort -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Release to artifactory') {
|
||||
when {
|
||||
branch 'issue/*'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'adoptopenjdk/openjdk8:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 20, unit: 'MINUTES') }
|
||||
|
||||
stage('Release to artifactory') {
|
||||
when {
|
||||
anyOf {
|
||||
branch '2.2.x'
|
||||
not { triggeredBy 'UpstreamCause' }
|
||||
}
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'adoptopenjdk/openjdk8:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 20, unit: 'MINUTES') }
|
||||
environment {
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
}
|
||||
|
||||
environment {
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
}
|
||||
steps {
|
||||
sh 'rm -rf ?'
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,artifactory ' +
|
||||
'-Dartifactory.server=https://repo.spring.io ' +
|
||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.staging-repository=libs-snapshot-local " +
|
||||
"-Dartifactory.build-name=spring-data-mongodb-2.1 " +
|
||||
"-Dartifactory.build-number=${BUILD_NUMBER} " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
}
|
||||
|
||||
steps {
|
||||
sh 'rm -rf ?'
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,artifactory ' +
|
||||
'-Dartifactory.server=https://repo.spring.io ' +
|
||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.staging-repository=libs-snapshot-local " +
|
||||
"-Dartifactory.build-name=spring-data-mongodb " +
|
||||
"-Dartifactory.build-number=${BUILD_NUMBER} " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
}
|
||||
stage('Release to artifactory with docs') {
|
||||
when {
|
||||
branch '2.1.x'
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'adoptopenjdk/openjdk8:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 20, unit: 'MINUTES') }
|
||||
|
||||
stage('Publish documentation') {
|
||||
when {
|
||||
branch '2.2.x'
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'adoptopenjdk/openjdk8:latest'
|
||||
label 'data'
|
||||
args '-v $HOME:/tmp/jenkins-home'
|
||||
}
|
||||
}
|
||||
options { timeout(time: 20, unit: 'MINUTES') }
|
||||
environment {
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
}
|
||||
|
||||
environment {
|
||||
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
|
||||
}
|
||||
steps {
|
||||
sh 'rm -rf ?'
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,artifactory ' +
|
||||
'-Dartifactory.server=https://repo.spring.io ' +
|
||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.staging-repository=libs-snapshot-local " +
|
||||
"-Dartifactory.build-name=spring-data-mongodb-2.1 " +
|
||||
"-Dartifactory.build-number=${BUILD_NUMBER} " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
steps {
|
||||
sh 'MAVEN_OPTS="-Duser.name=jenkins -Duser.home=/tmp/jenkins-home" ./mvnw -Pci,distribute ' +
|
||||
'-Dartifactory.server=https://repo.spring.io ' +
|
||||
"-Dartifactory.username=${ARTIFACTORY_USR} " +
|
||||
"-Dartifactory.password=${ARTIFACTORY_PSW} " +
|
||||
"-Dartifactory.distribution-repository=temp-private-local " +
|
||||
'-Dmaven.test.skip=true clean deploy -U -B'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
changed {
|
||||
script {
|
||||
slackSend(
|
||||
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
|
||||
channel: '#spring-data-dev',
|
||||
message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\n${env.BUILD_URL}")
|
||||
emailext(
|
||||
subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}",
|
||||
mimeType: 'text/html',
|
||||
recipientProviders: [[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']],
|
||||
body: "<a href=\"${env.BUILD_URL}\">${currentBuild.fullDisplayName} is reported as ${currentBuild.currentResult}</a>")
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
changed {
|
||||
script {
|
||||
slackSend(
|
||||
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
|
||||
channel: '#spring-data-dev',
|
||||
message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\n${env.BUILD_URL}")
|
||||
emailext(
|
||||
subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}",
|
||||
mimeType: 'text/html',
|
||||
recipientProviders: [[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']],
|
||||
body: "<a href=\"${env.BUILD_URL}\">${currentBuild.fullDisplayName} is reported as ${currentBuild.currentResult}</a>")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Please see the https://spring.io/projects/spring-data-mongodb[Spring Data MongoDB] project page for supported versions.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please don't raise security vulnerabilities here. Head over to https://pivotal.io/security to learn how to disclose them responsibly.
|
||||
@@ -1,39 +0,0 @@
|
||||
== Running CI tasks locally
|
||||
|
||||
Since Concourse is built on top of Docker, it's easy to:
|
||||
|
||||
* Debug what went wrong on your local machine.
|
||||
* Test out a a tweak to your `test.sh` script before sending it out.
|
||||
* Experiment against a new image before submitting your pull request.
|
||||
|
||||
All of these use cases are great reasons to essentially run what Concourse does on your local machine.
|
||||
|
||||
IMPORTANT: To do this you must have Docker installed on your machine.
|
||||
|
||||
1. `docker run -it --mount type=bind,source="$(pwd)",target=/spring-data-mongodb-github springci/spring-data-8-jdk-with-mongodb /bin/bash`
|
||||
+
|
||||
This will launch the Docker image and mount your source code at `spring-data-mongodb-github`.
|
||||
+
|
||||
Next, run the `test.sh` script from inside the container:
|
||||
+
|
||||
2. `PROFILE=none spring-data-mongodb-github/ci/test.sh`
|
||||
|
||||
Since the container is binding to your source, you can make edits from your IDE and continue to run build jobs.
|
||||
|
||||
If you need to test the `build.sh` script, do this:
|
||||
|
||||
1. `mkdir /tmp/spring-data-mongodb-artifactory`
|
||||
2. `docker run -it --mount type=bind,source="$(pwd)",target=/spring-data-mongodb-github --mount type=bind,source="/tmp/spring-data-mongodb-artifactory",target=/spring-data-mongodb-artifactory springci/spring-data-8-jdk-with-mongodb /bin/bash`
|
||||
+
|
||||
This will launch the Docker image and mount your source code at `spring-data-mongodb-github` and the temporary
|
||||
artifactory output directory at `spring-data-mongodb-artifactory`.
|
||||
+
|
||||
Next, run the `build.sh` script from inside the container:
|
||||
+
|
||||
3. `spring-data-mongodb-github/ci/build.sh`
|
||||
|
||||
IMPORTANT: `build.sh` doesn't actually push to Artifactory so don't worry about accidentally deploying anything.
|
||||
It just deploys to a local folder. That way, the `artifactory-resource` later in the pipeline can pick up these artifacts
|
||||
and deliver them to artifactory.
|
||||
|
||||
NOTE: Docker containers can eat up disk space fast! From time to time, run `docker system prune` to clean out old images.
|
||||
@@ -1,14 +0,0 @@
|
||||
FROM adoptopenjdk/openjdk8:latest
|
||||
|
||||
RUN apt-get update && apt-get install -y apt-transport-https apt-utils gnupg2
|
||||
|
||||
RUN apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv e162f504a20cdf15827f718d4b7c549a058f8b6b
|
||||
|
||||
RUN echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get install -y mongodb-org=4.2.0 mongodb-org-server=4.2.0 mongodb-org-shell=4.2.0 mongodb-org-mongos=4.2.0 mongodb-org-tools=4.2.0
|
||||
|
||||
RUN apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
31
pom.xml
31
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.2.8.RELEASE</version>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
@@ -15,20 +15,21 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>2.2.8.RELEASE</version>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
<module>spring-data-mongodb-cross-store</module>
|
||||
<module>spring-data-mongodb-distribution</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
<springdata.commons>2.2.8.RELEASE</springdata.commons>
|
||||
<mongo>3.11.2</mongo>
|
||||
<mongo.reactivestreams>1.12.0</mongo.reactivestreams>
|
||||
<springdata.commons>2.1.18.RELEASE</springdata.commons>
|
||||
<mongo>3.8.2</mongo>
|
||||
<mongo.reactivestreams>1.9.2</mongo.reactivestreams>
|
||||
<jmh.version>1.19</jmh.version>
|
||||
</properties>
|
||||
|
||||
@@ -117,10 +118,30 @@
|
||||
<id>benchmarks</id>
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
<module>spring-data-mongodb-cross-store</module>
|
||||
<module>spring-data-mongodb-distribution</module>
|
||||
<module>spring-data-mongodb-benchmarks</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>distribute</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<attributes>
|
||||
<mongo-reactivestreams>${mongo.reactivestreams}</mongo-reactivestreams>
|
||||
<reactor>${reactor}</reactor>
|
||||
</attributes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.2.8.RELEASE</version>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -87,7 +87,6 @@
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory>
|
||||
<testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory>
|
||||
<excludes>
|
||||
|
||||
7
spring-data-mongodb-cross-store/aop.xml
Normal file
7
spring-data-mongodb-cross-store/aop.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<aspectj>
|
||||
<aspects>
|
||||
<aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect" />
|
||||
<aspect name="org.springframework.data.mongodb.crossstore.MongoDocumentBacking" />
|
||||
</aspects>
|
||||
</aspectj>
|
||||
148
spring-data-mongodb-cross-store/pom.xml
Normal file
148
spring-data-mongodb-cross-store/pom.xml
Normal file
@@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
||||
<name>Spring Data MongoDB - Cross-Store Support</name>
|
||||
|
||||
<properties>
|
||||
<jpa>2.1.1</jpa>
|
||||
<hibernate>5.2.1.Final</hibernate>
|
||||
<java-module-name>spring.data.mongodb.cross.store</java-module-name>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Data -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!-- reactive -->
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JPA -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>javax.persistence</artifactId>
|
||||
<version>${jpa}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- For Tests -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>${hibernate}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>1.8.0.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${validation}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>5.2.4.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjtools</artifactId>
|
||||
<version>${aspectj}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<outxml>true</outxml>
|
||||
<aspectLibraries>
|
||||
<aspectLibrary>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aspects</artifactId>
|
||||
</aspectLibrary>
|
||||
</aspectLibraries>
|
||||
<complianceLevel>${source.level}</complianceLevel>
|
||||
<source>${source.level}</source>
|
||||
<target>${source.level}</target>
|
||||
<xmlConfigured>aop.xml</xmlConfigured>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,15 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository;
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import lombok.Value;
|
||||
import org.springframework.data.crossstore.ChangeSetBacked;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
* @deprecated will be removed without replacement.
|
||||
*/
|
||||
@Value
|
||||
class SumAge {
|
||||
@Deprecated
|
||||
public interface DocumentBacked extends ChangeSetBacked {
|
||||
|
||||
private Long total;
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.crossstore.ChangeSet;
|
||||
import org.springframework.data.crossstore.ChangeSetBacked;
|
||||
import org.springframework.data.crossstore.ChangeSetPersister;
|
||||
import org.springframework.data.mongodb.core.CollectionCallback;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.result.DeleteResult;
|
||||
|
||||
/**
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
* @author Alex Vengrovsk
|
||||
* @author Mark Paluch
|
||||
* @deprecated will be removed without replacement.
|
||||
*/
|
||||
@Deprecated
|
||||
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
|
||||
|
||||
private static final String ENTITY_CLASS = "_entity_class";
|
||||
private static final String ENTITY_ID = "_entity_id";
|
||||
private static final String ENTITY_FIELD_NAME = "_entity_field_name";
|
||||
private static final String ENTITY_FIELD_CLASS = "_entity_field_class";
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private MongoTemplate mongoTemplate;
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
public void setMongoTemplate(MongoTemplate mongoTemplate) {
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentState(java.lang.Class, java.lang.Object, org.springframework.data.crossstore.ChangeSet)
|
||||
*/
|
||||
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, final ChangeSet changeSet)
|
||||
throws DataAccessException, NotFoundException {
|
||||
|
||||
if (id == null) {
|
||||
log.debug("Unable to load MongoDB data for null id");
|
||||
return;
|
||||
}
|
||||
|
||||
String collName = getCollectionNameForEntity(entityClass);
|
||||
|
||||
final Document dbk = new Document();
|
||||
dbk.put(ENTITY_ID, id);
|
||||
dbk.put(ENTITY_CLASS, entityClass.getName());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Loading MongoDB data for {}", dbk);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
|
||||
for (Document dbo : collection.find(dbk)) {
|
||||
String key = (String) dbo.get(ENTITY_FIELD_NAME);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Processing key: {}", key);
|
||||
}
|
||||
if (!changeSet.getValues().containsKey(key)) {
|
||||
String className = (String) dbo.get(ENTITY_FIELD_CLASS);
|
||||
if (className == null) {
|
||||
throw new DataIntegrityViolationException(
|
||||
"Unble to convert property " + key + ": Invalid metadata, " + ENTITY_FIELD_CLASS + " not available");
|
||||
}
|
||||
Class<?> clazz = ClassUtils.resolveClassName(className, ClassUtils.getDefaultClassLoader());
|
||||
Object value = mongoTemplate.getConverter().read(clazz, dbo);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Adding to ChangeSet: {}", key);
|
||||
}
|
||||
changeSet.set(key, value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.crossstore.ChangeSetPersister#getPersistentId(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
||||
*/
|
||||
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("getPersistentId called on {}", entity);
|
||||
}
|
||||
if (entityManagerFactory == null) {
|
||||
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
|
||||
}
|
||||
|
||||
return entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.crossstore.ChangeSetPersister#persistState(org.springframework.data.crossstore.ChangeSetBacked, org.springframework.data.crossstore.ChangeSet)
|
||||
*/
|
||||
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
|
||||
if (cs == null) {
|
||||
log.debug("Flush: changeset was null, nothing to flush.");
|
||||
return 0L;
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: changeset: {}", cs.getValues());
|
||||
}
|
||||
|
||||
String collName = getCollectionNameForEntity(entity.getClass());
|
||||
if (mongoTemplate.getCollection(collName) == null) {
|
||||
mongoTemplate.createCollection(collName);
|
||||
}
|
||||
|
||||
for (String key : cs.getValues().keySet()) {
|
||||
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
|
||||
Object value = cs.getValues().get(key);
|
||||
final Document dbQuery = new Document();
|
||||
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
|
||||
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
|
||||
dbQuery.put(ENTITY_FIELD_NAME, key);
|
||||
final Document dbId = mongoTemplate.execute(collName, new CollectionCallback<Document>() {
|
||||
public Document doInCollection(MongoCollection<Document> collection)
|
||||
throws MongoException, DataAccessException {
|
||||
Document id = collection.find(dbQuery).first();
|
||||
return id;
|
||||
}
|
||||
});
|
||||
|
||||
if (value == null) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: removing: {}", dbQuery);
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(MongoCollection<Document> collection)
|
||||
throws MongoException, DataAccessException {
|
||||
DeleteResult dr = collection.deleteMany(dbQuery);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final Document dbDoc = new Document();
|
||||
dbDoc.putAll(dbQuery);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flush: saving: {}", dbQuery);
|
||||
}
|
||||
mongoTemplate.getConverter().write(value, dbDoc);
|
||||
dbDoc.put(ENTITY_FIELD_CLASS, value.getClass().getName());
|
||||
if (dbId != null) {
|
||||
dbDoc.put("_id", dbId.get("_id"));
|
||||
}
|
||||
mongoTemplate.execute(collName, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(MongoCollection<Document> collection)
|
||||
throws MongoException, DataAccessException {
|
||||
|
||||
if (dbId != null) {
|
||||
collection.replaceOne(Filters.eq("_id", dbId.get("_id")), dbDoc);
|
||||
} else {
|
||||
|
||||
if (dbDoc.containsKey("_id") && dbDoc.get("_id") == null) {
|
||||
dbDoc.remove("_id");
|
||||
}
|
||||
collection.insertOne(dbDoc);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the collection the given entity type shall be persisted to.
|
||||
*
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
|
||||
return mongoTemplate.getCollectionName(entityClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright 2011-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.reflect.FieldSignature;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.mongodb.crossstore.RelatedDocument;
|
||||
import org.springframework.data.mongodb.crossstore.DocumentBacked;
|
||||
import org.springframework.data.crossstore.ChangeSetBackedTransactionSynchronization;
|
||||
import org.springframework.data.crossstore.ChangeSet;
|
||||
import org.springframework.data.crossstore.ChangeSetPersister;
|
||||
import org.springframework.data.crossstore.ChangeSetPersister.NotFoundException;
|
||||
import org.springframework.data.crossstore.HashMapChangeSet;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
/**
|
||||
* Aspect to turn an object annotated with @Document into a persistent document using Mongo.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @deprecated will be removed without replacement.
|
||||
*/
|
||||
@Deprecated
|
||||
public aspect MongoDocumentBacking {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MongoDocumentBacking.class);
|
||||
|
||||
// Aspect shared config
|
||||
private ChangeSetPersister<Object> changeSetPersister;
|
||||
|
||||
public void setChangeSetPersister(ChangeSetPersister<Object> changeSetPersister) {
|
||||
this.changeSetPersister = changeSetPersister;
|
||||
}
|
||||
|
||||
// ITD to introduce N state to Annotated objects
|
||||
declare parents : (@Entity *) implements DocumentBacked;
|
||||
|
||||
// The annotated fields that will be persisted in MongoDB rather than with JPA
|
||||
declare @field: @RelatedDocument * (@Entity+ *).*:@Transient;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Advise user-defined constructors of ChangeSetBacked objects to create a new
|
||||
// backing ChangeSet
|
||||
// -------------------------------------------------------------------------
|
||||
pointcut arbitraryUserConstructorOfChangeSetBackedObject(DocumentBacked entity) :
|
||||
execution((DocumentBacked+).new(..)) &&
|
||||
!execution((DocumentBacked+).new(ChangeSet)) &&
|
||||
this(entity);
|
||||
|
||||
pointcut finderConstructorOfChangeSetBackedObject(DocumentBacked entity, ChangeSet cs) :
|
||||
execution((DocumentBacked+).new(ChangeSet)) &&
|
||||
this(entity) &&
|
||||
args(cs);
|
||||
|
||||
protected pointcut entityFieldGet(DocumentBacked entity) :
|
||||
get(@RelatedDocument * DocumentBacked+.*) &&
|
||||
this(entity) &&
|
||||
!get(* DocumentBacked.*);
|
||||
|
||||
protected pointcut entityFieldSet(DocumentBacked entity, Object newVal) :
|
||||
set(@RelatedDocument * DocumentBacked+.*) &&
|
||||
this(entity) &&
|
||||
args(newVal) &&
|
||||
!set(* DocumentBacked.*);
|
||||
|
||||
// intercept EntityManager.merge calls
|
||||
public pointcut entityManagerMerge(EntityManager em, Object entity) :
|
||||
call(* EntityManager.merge(Object)) &&
|
||||
target(em) &&
|
||||
args(entity);
|
||||
|
||||
// intercept EntityManager.remove calls
|
||||
// public pointcut entityManagerRemove(EntityManager em, Object entity) :
|
||||
// call(* EntityManager.remove(Object)) &&
|
||||
// target(em) &&
|
||||
// args(entity);
|
||||
|
||||
// move changeSet from detached entity to the newly merged persistent object
|
||||
Object around(EntityManager em, Object entity) : entityManagerMerge(em, entity) {
|
||||
Object mergedEntity = proceed(em, entity);
|
||||
if (entity instanceof DocumentBacked && mergedEntity instanceof DocumentBacked) {
|
||||
((DocumentBacked) mergedEntity).changeSet = ((DocumentBacked) entity).getChangeSet();
|
||||
}
|
||||
return mergedEntity;
|
||||
}
|
||||
|
||||
// clear changeSet from removed entity
|
||||
// Object around(EntityManager em, Object entity) : entityManagerRemove(em, entity) {
|
||||
// if (entity instanceof DocumentBacked) {
|
||||
// removeChangeSetValues((DocumentBacked)entity);
|
||||
// }
|
||||
// return proceed(em, entity);
|
||||
// }
|
||||
|
||||
private static void removeChangeSetValues(DocumentBacked entity) {
|
||||
LOGGER.debug("Removing all change-set values for " + entity);
|
||||
ChangeSet nulledCs = new HashMapChangeSet();
|
||||
DocumentBacked documentEntity = (DocumentBacked) entity;
|
||||
@SuppressWarnings("unchecked")
|
||||
ChangeSetPersister<Object> changeSetPersister = (ChangeSetPersister<Object>) documentEntity.itdChangeSetPersister;
|
||||
try {
|
||||
changeSetPersister.getPersistentState(documentEntity.getClass(), documentEntity.get_persistent_id(),
|
||||
documentEntity.getChangeSet());
|
||||
} catch (DataAccessException e) {
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
for (String key : entity.getChangeSet().getValues().keySet()) {
|
||||
nulledCs.set(key, null);
|
||||
}
|
||||
entity.setChangeSet(nulledCs);
|
||||
}
|
||||
|
||||
before(DocumentBacked entity) : arbitraryUserConstructorOfChangeSetBackedObject(entity) {
|
||||
LOGGER.debug("User-defined constructor called on DocumentBacked object of class " + entity.getClass());
|
||||
// Populate all ITD fields
|
||||
entity.setChangeSet(new HashMapChangeSet());
|
||||
entity.itdChangeSetPersister = changeSetPersister;
|
||||
entity.itdTransactionSynchronization = new ChangeSetBackedTransactionSynchronization(changeSetPersister, entity);
|
||||
// registerTransactionSynchronization(entity);
|
||||
}
|
||||
|
||||
private static void registerTransactionSynchronization(DocumentBacked entity) {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
if (!TransactionSynchronizationManager.getSynchronizations().contains(entity.itdTransactionSynchronization)) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Adding transaction synchronization for " + entity);
|
||||
}
|
||||
TransactionSynchronizationManager.registerSynchronization(entity.itdTransactionSynchronization);
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Transaction synchronization already active for " + entity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Transaction synchronization is not active for " + entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ChangeSet-related mixins
|
||||
// -------------------------------------------------------------------------
|
||||
// Introduced field
|
||||
@Transient
|
||||
private ChangeSet DocumentBacked.changeSet;
|
||||
|
||||
@Transient
|
||||
private ChangeSetPersister<?> DocumentBacked.itdChangeSetPersister;
|
||||
|
||||
@Transient
|
||||
private ChangeSetBackedTransactionSynchronization DocumentBacked.itdTransactionSynchronization;
|
||||
|
||||
public void DocumentBacked.setChangeSet(ChangeSet cs) {
|
||||
this.changeSet = cs;
|
||||
}
|
||||
|
||||
public ChangeSet DocumentBacked.getChangeSet() {
|
||||
return changeSet;
|
||||
}
|
||||
|
||||
// Flush the entity state to the persistent store
|
||||
public void DocumentBacked.flush() {
|
||||
Object id = itdChangeSetPersister.getPersistentId(this, this.changeSet);
|
||||
itdChangeSetPersister.persistState(this, this.changeSet);
|
||||
}
|
||||
|
||||
public Object DocumentBacked.get_persistent_id() {
|
||||
return itdChangeSetPersister.getPersistentId(this, this.changeSet);
|
||||
}
|
||||
|
||||
// lifecycle methods
|
||||
@javax.persistence.PostPersist
|
||||
public void DocumentBacked.itdPostPersist() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PrePersist: " + this.getClass().getName());
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PreUpdate
|
||||
public void DocumentBacked.itdPreUpdate() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PreUpdate: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PostUpdate
|
||||
public void DocumentBacked.itdPostUpdate() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostUpdate: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PostRemove
|
||||
public void DocumentBacked.itdPostRemove() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostRemove: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
removeChangeSetValues(this);
|
||||
}
|
||||
|
||||
@javax.persistence.PostLoad
|
||||
public void DocumentBacked.itdPostLoad() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JPA lifecycle event PostLoad: " + this.getClass().getName() + " :: " + this);
|
||||
}
|
||||
registerTransactionSynchronization(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates field reads to the state accessors instance
|
||||
*/
|
||||
Object around(DocumentBacked entity): entityFieldGet(entity) {
|
||||
Field f = field(thisJoinPoint);
|
||||
String propName = f.getName();
|
||||
LOGGER.trace("GET " + f + " -> ChangeSet value property [" + propName + "] using: " + entity.getChangeSet());
|
||||
if (entity.getChangeSet().getValues().get(propName) == null) {
|
||||
try {
|
||||
this.changeSetPersister
|
||||
.getPersistentState(entity.getClass(), entity.get_persistent_id(), entity.getChangeSet());
|
||||
} catch (NotFoundException e) {
|
||||
}
|
||||
}
|
||||
Object fValue = entity.getChangeSet().getValues().get(propName);
|
||||
if (fValue != null) {
|
||||
return fValue;
|
||||
}
|
||||
return proceed(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates field writes to the state accessors instance
|
||||
*/
|
||||
Object around(DocumentBacked entity, Object newVal) : entityFieldSet(entity, newVal) {
|
||||
Field f = field(thisJoinPoint);
|
||||
String propName = f.getName();
|
||||
LOGGER.trace("SET " + f + " -> ChangeSet number value property [" + propName + "] with value=[" + newVal + "]");
|
||||
entity.getChangeSet().set(propName, newVal);
|
||||
return proceed(entity, newVal);
|
||||
}
|
||||
|
||||
Field field(JoinPoint joinPoint) {
|
||||
FieldSignature fieldSignature = (FieldSignature) joinPoint.getSignature();
|
||||
return fieldSignature.getField();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,24 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.util.json;
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* A value provider to retrieve bindable values by their parameter index.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
* @author Thomas Risberg
|
||||
* @deprecated will be removed without replacement.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ValueProvider {
|
||||
|
||||
/**
|
||||
* @param index parameter index to use.
|
||||
* @return can be {@literal null}.
|
||||
* @throws RuntimeException if the requested element does not exist.
|
||||
*/
|
||||
@Nullable
|
||||
Object getBindableValue(int index);
|
||||
@Deprecated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD })
|
||||
public @interface RelatedDocument {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Infrastructure for Spring Data's MongoDB cross store support.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.crossstore.test.Address;
|
||||
import org.springframework.data.mongodb.crossstore.test.Person;
|
||||
import org.springframework.data.mongodb.crossstore.test.Resume;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
/**
|
||||
* Integration tests for MongoDB cross-store persistence (mainly {@link MongoChangeSetPersister}).
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:/META-INF/spring/applicationContext.xml")
|
||||
public class CrossStoreMongoTests {
|
||||
|
||||
@Autowired MongoTemplate mongoTemplate;
|
||||
|
||||
@PersistenceContext EntityManager entityManager;
|
||||
|
||||
@Autowired PlatformTransactionManager transactionManager;
|
||||
TransactionTemplate txTemplate;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
txTemplate = new TransactionTemplate(transactionManager);
|
||||
|
||||
clearData(Person.class);
|
||||
|
||||
Address address = new Address(12, "MAin St.", "Boston", "MA", "02101");
|
||||
|
||||
Resume resume = new Resume();
|
||||
resume.addEducation("Skanstulls High School, 1975");
|
||||
resume.addEducation("Univ. of Stockholm, 1980");
|
||||
resume.addJob("DiMark, DBA, 1990-2000");
|
||||
resume.addJob("VMware, Developer, 2007-");
|
||||
|
||||
final Person person = new Person("Thomas", 20);
|
||||
person.setAddress(address);
|
||||
person.setResume(resume);
|
||||
person.setId(1L);
|
||||
|
||||
txTemplate.execute(new TransactionCallback<Void>() {
|
||||
public Void doInTransaction(TransactionStatus status) {
|
||||
entityManager.persist(person);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
txTemplate.execute(new TransactionCallback<Void>() {
|
||||
public Void doInTransaction(TransactionStatus status) {
|
||||
entityManager.remove(entityManager.find(Person.class, 1L));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearData(Class<?> domainType) {
|
||||
|
||||
String collectionName = mongoTemplate.getCollectionName(domainType);
|
||||
mongoTemplate.dropCollection(collectionName);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testReadJpaToMongoEntityRelationship() {
|
||||
|
||||
Person found = entityManager.find(Person.class, 1L);
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; " + "VMware, Developer, 2007-", found.getResume().getJobs());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testUpdatedJpaToMongoEntityRelationship() {
|
||||
|
||||
Person found = entityManager.find(Person.class, 1L);
|
||||
found.setAge(44);
|
||||
found.getResume().addJob("SpringDeveloper.com, Consultant, 2005-2006");
|
||||
|
||||
entityManager.merge(found);
|
||||
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found);
|
||||
Assert.assertEquals(Long.valueOf(1), found.getId());
|
||||
Assert.assertNotNull(found.getResume());
|
||||
Assert.assertEquals("DiMark, DBA, 1990-2000" + "; " + "VMware, Developer, 2007-" + "; "
|
||||
+ "SpringDeveloper.com, Consultant, 2005-2006", found.getResume().getJobs());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeJpaEntityWithMongoDocument() {
|
||||
|
||||
final Person detached = entityManager.find(Person.class, 1L);
|
||||
entityManager.detach(detached);
|
||||
detached.getResume().addJob("TargetRx, Developer, 2000-2005");
|
||||
|
||||
Person merged = txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
Person result = entityManager.merge(detached);
|
||||
entityManager.flush();
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue(detached.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
||||
Assert.assertTrue(merged.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
||||
final Person updated = entityManager.find(Person.class, 1L);
|
||||
Assert.assertTrue(updated.getResume().getJobs().contains("TargetRx, Developer, 2000-2005"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveJpaEntityWithMongoDocument() {
|
||||
|
||||
txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
Person p2 = new Person("Thomas", 20);
|
||||
Resume r2 = new Resume();
|
||||
r2.addEducation("Skanstulls High School, 1975");
|
||||
r2.addJob("DiMark, DBA, 1990-2000");
|
||||
p2.setResume(r2);
|
||||
p2.setId(2L);
|
||||
entityManager.persist(p2);
|
||||
Person p3 = new Person("Thomas", 20);
|
||||
Resume r3 = new Resume();
|
||||
r3.addEducation("Univ. of Stockholm, 1980");
|
||||
r3.addJob("VMware, Developer, 2007-");
|
||||
p3.setResume(r3);
|
||||
p3.setId(3L);
|
||||
entityManager.persist(p3);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
txTemplate.execute(new TransactionCallback<Person>() {
|
||||
public Person doInTransaction(TransactionStatus status) {
|
||||
final Person found2 = entityManager.find(Person.class, 2L);
|
||||
entityManager.remove(found2);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
boolean weFound3 = false;
|
||||
|
||||
for (Document dbo : this.mongoTemplate.getCollection(mongoTemplate.getCollectionName(Person.class)).find()) {
|
||||
Assert.assertTrue(!dbo.get("_entity_id").equals(2L));
|
||||
if (dbo.get("_entity_id").equals(3L)) {
|
||||
weFound3 = true;
|
||||
}
|
||||
}
|
||||
Assert.assertTrue(weFound3);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore.test;
|
||||
|
||||
public class Address {
|
||||
|
||||
private Integer streetNumber;
|
||||
private String streetName;
|
||||
private String city;
|
||||
private String state;
|
||||
private String zip;
|
||||
|
||||
public Address(Integer streetNumber, String streetName, String city, String state, String zip) {
|
||||
super();
|
||||
this.streetNumber = streetNumber;
|
||||
this.streetName = streetName;
|
||||
this.city = city;
|
||||
this.state = state;
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
public Integer getStreetNumber() {
|
||||
return streetNumber;
|
||||
}
|
||||
|
||||
public void setStreetNumber(Integer streetNumber) {
|
||||
this.streetNumber = streetNumber;
|
||||
}
|
||||
|
||||
public String getStreetName() {
|
||||
return streetName;
|
||||
}
|
||||
|
||||
public void setStreetName(String streetName) {
|
||||
this.streetName = streetName;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getZip() {
|
||||
return zip;
|
||||
}
|
||||
|
||||
public void setZip(String zip) {
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore.test;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.springframework.data.mongodb.crossstore.RelatedDocument;
|
||||
|
||||
@Entity
|
||||
public class Person {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
private java.util.Date birthDate;
|
||||
|
||||
@RelatedDocument
|
||||
private Address address;
|
||||
|
||||
@RelatedDocument
|
||||
private Resume resume;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String name, int age) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.birthDate = new java.util.Date();
|
||||
}
|
||||
|
||||
public void birthday() {
|
||||
++age;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public java.util.Date getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(java.util.Date birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public Resume getResume() {
|
||||
return resume;
|
||||
}
|
||||
|
||||
public void setResume(Resume resume) {
|
||||
this.resume = resume;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.crossstore.test;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Document
|
||||
public class Resume {
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog(Resume.class);
|
||||
|
||||
@Id
|
||||
private ObjectId id;
|
||||
|
||||
private String education = "";
|
||||
|
||||
private String jobs = "";
|
||||
|
||||
public String getId() {
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
public String getEducation() {
|
||||
return education;
|
||||
}
|
||||
|
||||
public void addEducation(String education) {
|
||||
LOGGER.debug("Adding education " + education);
|
||||
this.education = this.education + (this.education.length() > 0 ? "; " : "") + education;
|
||||
}
|
||||
|
||||
public String getJobs() {
|
||||
return jobs;
|
||||
}
|
||||
|
||||
public void addJob(String job) {
|
||||
LOGGER.debug("Adding job " + job);
|
||||
this.jobs = this.jobs + (this.jobs.length() > 0 ? "; " : "") + job;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Resume [education=" + education + ", jobs=" + jobs + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
version="2.0"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<class>org.springframework.data.mongodb.crossstore.test.Person</class>
|
||||
<properties>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
|
||||
<!--value='create' to build a new database on each run; value='update' to modify an existing database; value='create-drop' means the same as 'create' but also drops tables when Hibernate closes; value='validate' makes no changes to the database-->
|
||||
<property name="hibernate.hbm2ddl.auto" value="update"/>
|
||||
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo https://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/jdbc https://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-3.0.xsd
|
||||
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<context:spring-configured/>
|
||||
|
||||
<context:component-scan base-package="org.springframework.persistence.mongodb.test">
|
||||
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
|
||||
</context:component-scan>
|
||||
|
||||
<mongo:mapping-converter/>
|
||||
|
||||
<!-- Mongo config -->
|
||||
<bean id="mongoClient" class="org.springframework.data.mongodb.core.MongoClientFactoryBean">
|
||||
<property name="host" value="localhost"/>
|
||||
<property name="port" value="27017"/>
|
||||
</bean>
|
||||
|
||||
<bean id="mongoDbFactory" class="org.springframework.data.mongodb.core.SimpleMongoDbFactory">
|
||||
<constructor-arg name="mongoClient" ref="mongoClient"/>
|
||||
<constructor-arg name="databaseName" value="database"/>
|
||||
</bean>
|
||||
|
||||
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
|
||||
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
|
||||
<constructor-arg name="mongoConverter" ref="mappingConverter"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.data.mongodb.core.MongoExceptionTranslator"/>
|
||||
|
||||
<!-- Mongo aspect config -->
|
||||
<bean class="org.springframework.data.mongodb.crossstore.MongoDocumentBacking"
|
||||
factory-method="aspectOf">
|
||||
<property name="changeSetPersister" ref="mongoChangeSetPersister"/>
|
||||
</bean>
|
||||
<bean id="mongoChangeSetPersister"
|
||||
class="org.springframework.data.mongodb.crossstore.MongoChangeSetPersister">
|
||||
<property name="mongoTemplate" ref="mongoTemplate"/>
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
|
||||
<jdbc:embedded-database id="dataSource" type="HSQL">
|
||||
</jdbc:embedded-database>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
|
||||
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
|
||||
|
||||
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
|
||||
<property name="persistenceUnitName" value="test"/>
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
<property name="jpaVendorAdapter">
|
||||
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
|
||||
<property name="showSql" value="true"/>
|
||||
<property name="generateDdl" value="true"/>
|
||||
<property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
<logger name="org.springframework" level="debug" />
|
||||
-->
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.2.8.RELEASE</version>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -32,15 +31,8 @@
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<attributes>
|
||||
<mongo-reactivestreams>${mongo.reactivestreams}</mongo-reactivestreams>
|
||||
<reactor>${reactor}</reactor>
|
||||
</attributes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>2.2.8.RELEASE</version>
|
||||
<version>2.1.18.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -83,14 +83,14 @@
|
||||
|
||||
<!-- reactive -->
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-reactivestreams</artifactId>
|
||||
<version>${mongo.reactivestreams}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongodb-driver-async</artifactId>
|
||||
<version>${mongo}</version>
|
||||
<optional>true</optional>
|
||||
@@ -107,7 +107,7 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -119,14 +119,14 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.reactivex</groupId>
|
||||
<groupId>io.reactivex</groupId>
|
||||
<artifactId>rxjava</artifactId>
|
||||
<version>${rxjava}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.reactivex</groupId>
|
||||
<groupId>io.reactivex</groupId>
|
||||
<artifactId>rxjava-reactive-streams</artifactId>
|
||||
<version>${rxjava-reactive-streams}</version>
|
||||
<optional>true</optional>
|
||||
@@ -264,25 +264,20 @@
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${kotlin}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
<version>${kotlin}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlinx</groupId>
|
||||
<artifactId>kotlinx-coroutines-reactor</artifactId>
|
||||
<optional>true</optional>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test</artifactId>
|
||||
<version>${kotlin}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -327,7 +322,6 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<useFile>false</useFile>
|
||||
<includes>
|
||||
<include>**/*Tests.java</include>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.data.authentication.UserCredentials;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Exception being thrown in case we cannot connect to a MongoDB instance.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException {
|
||||
|
||||
private final UserCredentials credentials;
|
||||
private final @Nullable String database;
|
||||
|
||||
private static final long serialVersionUID = 1172099106475265589L;
|
||||
|
||||
public CannotGetMongoDbConnectionException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
this.database = null;
|
||||
this.credentials = UserCredentials.NO_CREDENTIALS;
|
||||
}
|
||||
|
||||
public CannotGetMongoDbConnectionException(String msg) {
|
||||
this(msg, null, UserCredentials.NO_CREDENTIALS);
|
||||
}
|
||||
|
||||
public CannotGetMongoDbConnectionException(String msg, @Nullable String database, UserCredentials credentials) {
|
||||
super(msg);
|
||||
this.database = database;
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link UserCredentials} that were used when trying to connect to the MongoDB instance.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public UserCredentials getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the database trying to be accessed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public String getDatabase() {
|
||||
return database;
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,8 @@ public class LazyLoadingException extends UncategorizedDataAccessException {
|
||||
private static final long serialVersionUID = -7089224903873220037L;
|
||||
|
||||
/**
|
||||
* Constructor for LazyLoadingException.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param cause the exception thrown by underlying data access API.
|
||||
* @param msg
|
||||
* @param cause
|
||||
*/
|
||||
public LazyLoadingException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
|
||||
@@ -37,7 +37,7 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi
|
||||
/**
|
||||
* Creates a default {@link MongoDatabase} instance.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
MongoDatabase getDb() throws DataAccessException;
|
||||
@@ -46,7 +46,7 @@ public interface MongoDbFactory extends CodecRegistryProvider, MongoSessionProvi
|
||||
* Creates a {@link DB} instance to access the database with the given name.
|
||||
*
|
||||
* @param dbName must not be {@literal null} or empty.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
MongoDatabase getDb(String dbName) throws DataAccessException;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -38,7 +39,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
|
||||
/**
|
||||
* Creates a default {@link MongoDatabase} instance.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
MongoDatabase getMongoDatabase() throws DataAccessException;
|
||||
@@ -47,7 +48,7 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
|
||||
* Creates a {@link MongoDatabase} instance to access the database with the given name.
|
||||
*
|
||||
* @param dbName must not be {@literal null} or empty.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
MongoDatabase getMongoDatabase(String dbName) throws DataAccessException;
|
||||
@@ -87,16 +88,4 @@ public interface ReactiveMongoDatabaseFactory extends CodecRegistryProvider {
|
||||
* @since 2.1
|
||||
*/
|
||||
ReactiveMongoDatabaseFactory withSession(ClientSession session);
|
||||
|
||||
/**
|
||||
* Returns if the given {@link ReactiveMongoDatabaseFactory} is bound to a
|
||||
* {@link com.mongodb.reactivestreams.client.ClientSession} that has an
|
||||
* {@link com.mongodb.reactivestreams.client.ClientSession#hasActiveTransaction() active transaction}.
|
||||
*
|
||||
* @return {@literal true} if there's an active transaction, {@literal false} otherwise.
|
||||
* @since 2.2
|
||||
*/
|
||||
default boolean isTransactionActive() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.context.Context;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.NoTransactionException;
|
||||
import org.springframework.transaction.reactive.ReactiveResourceSynchronization;
|
||||
import org.springframework.transaction.reactive.TransactionSynchronization;
|
||||
import org.springframework.transaction.reactive.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.ResourceHolderSynchronization;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.ClientSessionOptions;
|
||||
import com.mongodb.reactivestreams.client.ClientSession;
|
||||
import com.mongodb.reactivestreams.client.MongoCollection;
|
||||
import com.mongodb.reactivestreams.client.MongoDatabase;
|
||||
|
||||
/**
|
||||
* Helper class for managing reactive {@link MongoDatabase} instances via {@link ReactiveMongoDatabaseFactory}. Used for
|
||||
* obtaining {@link ClientSession session bound} resources, such as {@link MongoDatabase} and {@link MongoCollection}
|
||||
* suitable for transactional usage.
|
||||
* <p />
|
||||
* <strong>Note:</strong> Intended for internal usage only.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
*/
|
||||
public class ReactiveMongoDatabaseUtils {
|
||||
|
||||
/**
|
||||
* Check if the {@link ReactiveMongoDatabaseFactory} is actually bound to a
|
||||
* {@link com.mongodb.reactivestreams.client.ClientSession} that has an active transaction, or if a
|
||||
* {@link org.springframework.transaction.reactive.TransactionSynchronization} has been registered for the
|
||||
* {@link ReactiveMongoDatabaseFactory resource} and if the associated
|
||||
* {@link com.mongodb.reactivestreams.client.ClientSession} has an
|
||||
* {@link com.mongodb.reactivestreams.client.ClientSession#hasActiveTransaction() active transaction}.
|
||||
*
|
||||
* @param databaseFactory the resource to check transactions for. Must not be {@literal null}.
|
||||
* @return a {@link Mono} emitting {@literal true} if the factory has an ongoing transaction.
|
||||
*/
|
||||
public static Mono<Boolean> isTransactionActive(ReactiveMongoDatabaseFactory databaseFactory) {
|
||||
|
||||
if (databaseFactory.isTransactionActive()) {
|
||||
return Mono.just(true);
|
||||
}
|
||||
|
||||
return TransactionSynchronizationManager.forCurrentTransaction() //
|
||||
.map(it -> {
|
||||
|
||||
ReactiveMongoResourceHolder holder = (ReactiveMongoResourceHolder) it.getResource(databaseFactory);
|
||||
return holder != null && holder.hasActiveTransaction();
|
||||
}) //
|
||||
.onErrorResume(NoTransactionException.class, e -> Mono.just(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the default {@link MongoDatabase database} form the given {@link ReactiveMongoDatabaseFactory factory} using
|
||||
* {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}.
|
||||
* <p />
|
||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber
|
||||
* {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
||||
*
|
||||
* @param factory the {@link ReactiveMongoDatabaseFactory} to get the {@link MongoDatabase} from.
|
||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
||||
*/
|
||||
public static Mono<MongoDatabase> getDatabase(ReactiveMongoDatabaseFactory factory) {
|
||||
return doGetMongoDatabase(null, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the default {@link MongoDatabase database} form the given {@link ReactiveMongoDatabaseFactory factory}.
|
||||
* <p />
|
||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber
|
||||
* {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
||||
*
|
||||
* @param factory the {@link ReactiveMongoDatabaseFactory} to get the {@link MongoDatabase} from.
|
||||
* @param sessionSynchronization the synchronization to use. Must not be {@literal null}.
|
||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
||||
*/
|
||||
public static Mono<MongoDatabase> getDatabase(ReactiveMongoDatabaseFactory factory,
|
||||
SessionSynchronization sessionSynchronization) {
|
||||
return doGetMongoDatabase(null, factory, sessionSynchronization);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the {@link MongoDatabase database} with given name form the given {@link ReactiveMongoDatabaseFactory
|
||||
* factory} using {@link SessionSynchronization#ON_ACTUAL_TRANSACTION native session synchronization}.
|
||||
* <p />
|
||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber
|
||||
* {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
||||
*
|
||||
* @param dbName the name of the {@link MongoDatabase} to get.
|
||||
* @param factory the {@link ReactiveMongoDatabaseFactory} to get the {@link MongoDatabase} from.
|
||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
||||
*/
|
||||
public static Mono<MongoDatabase> getDatabase(String dbName, ReactiveMongoDatabaseFactory factory) {
|
||||
return doGetMongoDatabase(dbName, factory, SessionSynchronization.ON_ACTUAL_TRANSACTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the {@link MongoDatabase database} with given name form the given {@link ReactiveMongoDatabaseFactory
|
||||
* factory}.
|
||||
* <p />
|
||||
* Registers a {@link MongoSessionSynchronization MongoDB specific transaction synchronization} within the subscriber
|
||||
* {@link Context} if {@link TransactionSynchronizationManager#isSynchronizationActive() synchronization is active}.
|
||||
*
|
||||
* @param dbName the name of the {@link MongoDatabase} to get.
|
||||
* @param factory the {@link ReactiveMongoDatabaseFactory} to get the {@link MongoDatabase} from.
|
||||
* @param sessionSynchronization the synchronization to use. Must not be {@literal null}.
|
||||
* @return the {@link MongoDatabase} that is potentially associated with a transactional {@link ClientSession}.
|
||||
*/
|
||||
public static Mono<MongoDatabase> getDatabase(String dbName, ReactiveMongoDatabaseFactory factory,
|
||||
SessionSynchronization sessionSynchronization) {
|
||||
return doGetMongoDatabase(dbName, factory, sessionSynchronization);
|
||||
}
|
||||
|
||||
private static Mono<MongoDatabase> doGetMongoDatabase(@Nullable String dbName, ReactiveMongoDatabaseFactory factory,
|
||||
SessionSynchronization sessionSynchronization) {
|
||||
|
||||
Assert.notNull(factory, "DatabaseFactory must not be null!");
|
||||
|
||||
return TransactionSynchronizationManager.forCurrentTransaction()
|
||||
.filter(TransactionSynchronizationManager::isSynchronizationActive) //
|
||||
.flatMap(synchronizationManager -> {
|
||||
|
||||
return doGetSession(synchronizationManager, factory, sessionSynchronization) //
|
||||
.map(it -> getMongoDatabaseOrDefault(dbName, factory.withSession(it)));
|
||||
})
|
||||
.onErrorResume(NoTransactionException.class,
|
||||
e -> Mono.fromSupplier(() -> getMongoDatabaseOrDefault(dbName, factory)))
|
||||
.defaultIfEmpty(getMongoDatabaseOrDefault(dbName, factory));
|
||||
}
|
||||
|
||||
private static MongoDatabase getMongoDatabaseOrDefault(@Nullable String dbName,
|
||||
ReactiveMongoDatabaseFactory factory) {
|
||||
return StringUtils.hasText(dbName) ? factory.getMongoDatabase(dbName) : factory.getMongoDatabase();
|
||||
}
|
||||
|
||||
private static Mono<ClientSession> doGetSession(TransactionSynchronizationManager synchronizationManager,
|
||||
ReactiveMongoDatabaseFactory dbFactory, SessionSynchronization sessionSynchronization) {
|
||||
|
||||
final ReactiveMongoResourceHolder registeredHolder = (ReactiveMongoResourceHolder) synchronizationManager
|
||||
.getResource(dbFactory);
|
||||
|
||||
// check for native MongoDB transaction
|
||||
if (registeredHolder != null
|
||||
&& (registeredHolder.hasSession() || registeredHolder.isSynchronizedWithTransaction())) {
|
||||
|
||||
return registeredHolder.hasSession() ? Mono.just(registeredHolder.getSession())
|
||||
: createClientSession(dbFactory).map(registeredHolder::setSessionIfAbsent);
|
||||
}
|
||||
|
||||
if (SessionSynchronization.ON_ACTUAL_TRANSACTION.equals(sessionSynchronization)) {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
// init a non native MongoDB transaction by registering a MongoSessionSynchronization
|
||||
return createClientSession(dbFactory).map(session -> {
|
||||
|
||||
ReactiveMongoResourceHolder newHolder = new ReactiveMongoResourceHolder(session, dbFactory);
|
||||
newHolder.getRequiredSession().startTransaction();
|
||||
|
||||
synchronizationManager
|
||||
.registerSynchronization(new MongoSessionSynchronization(synchronizationManager, newHolder, dbFactory));
|
||||
newHolder.setSynchronizedWithTransaction(true);
|
||||
synchronizationManager.bindResource(dbFactory, newHolder);
|
||||
|
||||
return newHolder.getSession();
|
||||
});
|
||||
}
|
||||
|
||||
private static Mono<ClientSession> createClientSession(ReactiveMongoDatabaseFactory dbFactory) {
|
||||
return dbFactory.getSession(ClientSessionOptions.builder().causallyConsistent(true).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* MongoDB specific {@link ResourceHolderSynchronization} for resource cleanup at the end of a transaction when
|
||||
* participating in a non-native MongoDB transaction, such as a R2CBC transaction.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.2
|
||||
*/
|
||||
private static class MongoSessionSynchronization
|
||||
extends ReactiveResourceSynchronization<ReactiveMongoResourceHolder, Object> {
|
||||
|
||||
private final ReactiveMongoResourceHolder resourceHolder;
|
||||
|
||||
MongoSessionSynchronization(TransactionSynchronizationManager synchronizationManager,
|
||||
ReactiveMongoResourceHolder resourceHolder, ReactiveMongoDatabaseFactory dbFactory) {
|
||||
|
||||
super(resourceHolder, dbFactory, synchronizationManager);
|
||||
this.resourceHolder = resourceHolder;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.ReactiveResourceSynchronization#shouldReleaseBeforeCompletion()
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldReleaseBeforeCompletion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.ReactiveResourceSynchronization#processResourceAfterCommit(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Void> processResourceAfterCommit(ReactiveMongoResourceHolder resourceHolder) {
|
||||
|
||||
if (isTransactionActive(resourceHolder)) {
|
||||
return Mono.from(resourceHolder.getRequiredSession().commitTransaction());
|
||||
}
|
||||
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.ReactiveResourceSynchronization#afterCompletion(int)
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> afterCompletion(int status) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
|
||||
if (status == TransactionSynchronization.STATUS_ROLLED_BACK && isTransactionActive(this.resourceHolder)) {
|
||||
|
||||
return Mono.from(resourceHolder.getRequiredSession().abortTransaction()) //
|
||||
.then(super.afterCompletion(status));
|
||||
}
|
||||
|
||||
return super.afterCompletion(status);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.ReactiveResourceSynchronization#releaseResource(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Void> releaseResource(ReactiveMongoResourceHolder resourceHolder, Object resourceKey) {
|
||||
|
||||
return Mono.fromRunnable(() -> {
|
||||
if (resourceHolder.hasActiveSession()) {
|
||||
resourceHolder.getRequiredSession().close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isTransactionActive(ReactiveMongoResourceHolder resourceHolder) {
|
||||
|
||||
if (!resourceHolder.hasSession()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return resourceHolder.getRequiredSession().hasActiveTransaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.support.ResourceHolderSupport;
|
||||
|
||||
import com.mongodb.reactivestreams.client.ClientSession;
|
||||
|
||||
/**
|
||||
* MongoDB specific resource holder, wrapping a {@link ClientSession}. {@link ReactiveMongoTransactionManager} binds
|
||||
* instances of this class to the subscriber context.
|
||||
* <p />
|
||||
* <strong>Note:</strong> Intended for internal usage only.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
* @see ReactiveMongoTransactionManager
|
||||
* @see ReactiveMongoTemplate
|
||||
*/
|
||||
class ReactiveMongoResourceHolder extends ResourceHolderSupport {
|
||||
|
||||
private @Nullable ClientSession session;
|
||||
private ReactiveMongoDatabaseFactory databaseFactory;
|
||||
|
||||
/**
|
||||
* Create a new {@link ReactiveMongoResourceHolder} for a given {@link ClientSession session}.
|
||||
*
|
||||
* @param session the associated {@link ClientSession}. Can be {@literal null}.
|
||||
* @param databaseFactory the associated {@link MongoDbFactory}. must not be {@literal null}.
|
||||
*/
|
||||
ReactiveMongoResourceHolder(@Nullable ClientSession session, ReactiveMongoDatabaseFactory databaseFactory) {
|
||||
|
||||
this.session = session;
|
||||
this.databaseFactory = databaseFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the associated {@link ClientSession}. Can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
ClientSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the required associated {@link ClientSession}.
|
||||
* @throws IllegalStateException if no session is associated.
|
||||
*/
|
||||
ClientSession getRequiredSession() {
|
||||
|
||||
ClientSession session = getSession();
|
||||
|
||||
if (session == null) {
|
||||
throw new IllegalStateException("No ClientSession associated");
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the associated {@link ReactiveMongoDatabaseFactory}.
|
||||
*/
|
||||
public ReactiveMongoDatabaseFactory getDatabaseFactory() {
|
||||
return databaseFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ClientSession} to guard.
|
||||
*
|
||||
* @param session can be {@literal null}.
|
||||
*/
|
||||
public void setSession(@Nullable ClientSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if session is not {@literal null}.
|
||||
*/
|
||||
boolean hasSession() {
|
||||
return session != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the {@link ReactiveMongoResourceHolder} is {@link #hasSession() not already associated} with a
|
||||
* {@link ClientSession} the given value is {@link #setSession(ClientSession) set} and returned, otherwise the current
|
||||
* bound session is returned.
|
||||
*
|
||||
* @param session
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public ClientSession setSessionIfAbsent(@Nullable ClientSession session) {
|
||||
|
||||
if (!hasSession()) {
|
||||
setSession(session);
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the session is active and has not been closed.
|
||||
*/
|
||||
boolean hasActiveSession() {
|
||||
|
||||
if (!hasSession()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return hasServerSession() && !getRequiredSession().getServerSession().isClosed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the session has an active transaction.
|
||||
* @see #hasActiveSession()
|
||||
*/
|
||||
boolean hasActiveTransaction() {
|
||||
|
||||
if (!hasActiveSession()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getRequiredSession().hasActiveTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the {@link ClientSession} has a {@link com.mongodb.session.ServerSession} associated
|
||||
* that is accessible via {@link ClientSession#getServerSession()}.
|
||||
*/
|
||||
boolean hasServerSession() {
|
||||
|
||||
try {
|
||||
return getRequiredSession().getServerSession() != null;
|
||||
} catch (IllegalStateException serverSessionClosed) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,530 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.reactive.AbstractReactiveTransactionManager;
|
||||
import org.springframework.transaction.reactive.GenericReactiveTransaction;
|
||||
import org.springframework.transaction.reactive.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.SmartTransactionObject;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.mongodb.ClientSessionOptions;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.TransactionOptions;
|
||||
import com.mongodb.reactivestreams.client.ClientSession;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.transaction.ReactiveTransactionManager} implementation that manages
|
||||
* {@link com.mongodb.reactivestreams.client.ClientSession} based transactions for a single
|
||||
* {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory}.
|
||||
* <p />
|
||||
* Binds a {@link ClientSession} from the specified
|
||||
* {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory} to the subscriber
|
||||
* {@link reactor.util.context.Context}.
|
||||
* <p />
|
||||
* {@link org.springframework.transaction.TransactionDefinition#isReadOnly() Readonly} transactions operate on a
|
||||
* {@link ClientSession} and enable causal consistency, and also {@link ClientSession#startTransaction() start},
|
||||
* {@link com.mongodb.reactivestreams.client.ClientSession#commitTransaction() commit} or
|
||||
* {@link ClientSession#abortTransaction() abort} a transaction.
|
||||
* <p />
|
||||
* Application code is required to retrieve the {@link com.mongodb.reactivestreams.client.MongoDatabase} via
|
||||
* {@link org.springframework.data.mongodb.ReactiveMongoDatabaseUtils#getDatabase(ReactiveMongoDatabaseFactory)} instead
|
||||
* of a standard {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#getMongoDatabase()} call. Spring
|
||||
* classes such as {@link org.springframework.data.mongodb.core.ReactiveMongoTemplate} use this strategy implicitly.
|
||||
* <p />
|
||||
* By default failure of a {@literal commit} operation raises a {@link TransactionSystemException}. You can override
|
||||
* {@link #doCommit(TransactionSynchronizationManager, ReactiveMongoTransactionObject)} to implement the
|
||||
* <a href="https://docs.mongodb.com/manual/core/transactions/#retry-commit-operation">Retry Commit Operation</a>
|
||||
* behavior as outlined in the MongoDB reference manual.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 2.2
|
||||
* @see <a href="https://www.mongodb.com/transactions">MongoDB Transaction Documentation</a>
|
||||
* @see ReactiveMongoDatabaseUtils#getDatabase(ReactiveMongoDatabaseFactory, SessionSynchronization)
|
||||
*/
|
||||
public class ReactiveMongoTransactionManager extends AbstractReactiveTransactionManager implements InitializingBean {
|
||||
|
||||
private @Nullable ReactiveMongoDatabaseFactory databaseFactory;
|
||||
private @Nullable TransactionOptions options;
|
||||
|
||||
/**
|
||||
* Create a new {@link ReactiveMongoTransactionManager} for bean-style usage.
|
||||
* <p />
|
||||
* <strong>Note:</strong>The {@link org.springframework.data.mongodb.ReactiveMongoDatabaseFactory db factory} has to
|
||||
* be {@link #setDatabaseFactory(ReactiveMongoDatabaseFactory)} set} before using the instance. Use this constructor
|
||||
* to prepare a {@link ReactiveMongoTransactionManager} via a {@link org.springframework.beans.factory.BeanFactory}.
|
||||
* <p />
|
||||
* Optionally it is possible to set default {@link TransactionOptions transaction options} defining
|
||||
* {@link com.mongodb.ReadConcern} and {@link com.mongodb.WriteConcern}.
|
||||
*
|
||||
* @see #setDatabaseFactory(ReactiveMongoDatabaseFactory)
|
||||
*/
|
||||
public ReactiveMongoTransactionManager() {}
|
||||
|
||||
/**
|
||||
* Create a new {@link ReactiveMongoTransactionManager} obtaining sessions from the given
|
||||
* {@link ReactiveMongoDatabaseFactory}.
|
||||
*
|
||||
* @param databaseFactory must not be {@literal null}.
|
||||
*/
|
||||
public ReactiveMongoTransactionManager(ReactiveMongoDatabaseFactory databaseFactory) {
|
||||
this(databaseFactory, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ReactiveMongoTransactionManager} obtaining sessions from the given
|
||||
* {@link ReactiveMongoDatabaseFactory} applying the given {@link TransactionOptions options}, if present, when
|
||||
* starting a new transaction.
|
||||
*
|
||||
* @param databaseFactory must not be {@literal null}.
|
||||
* @param options can be {@literal null}.
|
||||
*/
|
||||
public ReactiveMongoTransactionManager(ReactiveMongoDatabaseFactory databaseFactory,
|
||||
@Nullable TransactionOptions options) {
|
||||
|
||||
Assert.notNull(databaseFactory, "DatabaseFactory must not be null!");
|
||||
|
||||
this.databaseFactory = databaseFactory;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doGetTransaction(org.springframework.transaction.reactive.TransactionSynchronizationManager)
|
||||
*/
|
||||
@Override
|
||||
protected Object doGetTransaction(TransactionSynchronizationManager synchronizationManager)
|
||||
throws TransactionException {
|
||||
|
||||
ReactiveMongoResourceHolder resourceHolder = (ReactiveMongoResourceHolder) synchronizationManager
|
||||
.getResource(getRequiredDatabaseFactory());
|
||||
return new ReactiveMongoTransactionObject(resourceHolder);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#isExistingTransaction(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected boolean isExistingTransaction(Object transaction) throws TransactionException {
|
||||
return extractMongoTransaction(transaction).hasResourceHolder();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doBegin(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object, org.springframework.transaction.TransactionDefinition)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Void> doBegin(TransactionSynchronizationManager synchronizationManager, Object transaction,
|
||||
TransactionDefinition definition) throws TransactionException {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
|
||||
ReactiveMongoTransactionObject mongoTransactionObject = extractMongoTransaction(transaction);
|
||||
|
||||
Mono<ReactiveMongoResourceHolder> holder = newResourceHolder(definition,
|
||||
ClientSessionOptions.builder().causallyConsistent(true).build());
|
||||
|
||||
return holder.doOnNext(resourceHolder -> {
|
||||
|
||||
mongoTransactionObject.setResourceHolder(resourceHolder);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
String.format("About to start transaction for session %s.", debugString(resourceHolder.getSession())));
|
||||
}
|
||||
|
||||
}).doOnNext(resourceHolder -> {
|
||||
|
||||
mongoTransactionObject.startTransaction(options);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Started transaction for session %s.", debugString(resourceHolder.getSession())));
|
||||
}
|
||||
|
||||
})//
|
||||
.onErrorMap(
|
||||
ex -> new TransactionSystemException(String.format("Could not start Mongo transaction for session %s.",
|
||||
debugString(mongoTransactionObject.getSession())), ex))
|
||||
.doOnSuccess(resourceHolder -> {
|
||||
|
||||
synchronizationManager.bindResource(getRequiredDatabaseFactory(), resourceHolder);
|
||||
}).then();
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doSuspend(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Object> doSuspend(TransactionSynchronizationManager synchronizationManager, Object transaction)
|
||||
throws TransactionException {
|
||||
|
||||
return Mono.fromSupplier(() -> {
|
||||
|
||||
ReactiveMongoTransactionObject mongoTransactionObject = extractMongoTransaction(transaction);
|
||||
mongoTransactionObject.setResourceHolder(null);
|
||||
|
||||
return synchronizationManager.unbindResource(getRequiredDatabaseFactory());
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doResume(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Void> doResume(TransactionSynchronizationManager synchronizationManager, @Nullable Object transaction,
|
||||
Object suspendedResources) {
|
||||
return Mono
|
||||
.fromRunnable(() -> synchronizationManager.bindResource(getRequiredDatabaseFactory(), suspendedResources));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doCommit(org.springframework.transaction.reactive.TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction)
|
||||
*/
|
||||
@Override
|
||||
protected final Mono<Void> doCommit(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
|
||||
ReactiveMongoTransactionObject mongoTransactionObject = extractMongoTransaction(status);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("About to commit transaction for session %s.",
|
||||
debugString(mongoTransactionObject.getSession())));
|
||||
}
|
||||
|
||||
return doCommit(synchronizationManager, mongoTransactionObject).onErrorMap(ex -> {
|
||||
return new TransactionSystemException(String.format("Could not commit Mongo transaction for session %s.",
|
||||
debugString(mongoTransactionObject.getSession())), ex);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Customization hook to perform an actual commit of the given transaction.<br />
|
||||
* If a commit operation encounters an error, the MongoDB driver throws a {@link MongoException} holding
|
||||
* {@literal error labels}. <br />
|
||||
* By default those labels are ignored, nevertheless one might check for
|
||||
* {@link MongoException#UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL transient commit errors labels} and retry the the
|
||||
* commit.
|
||||
*
|
||||
* @param synchronizationManager reactive synchronization manager.
|
||||
* @param transactionObject never {@literal null}.
|
||||
*/
|
||||
protected Mono<Void> doCommit(TransactionSynchronizationManager synchronizationManager,
|
||||
ReactiveMongoTransactionObject transactionObject) {
|
||||
return transactionObject.commitTransaction();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doRollback(org.springframework.transaction.reactive.TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Void> doRollback(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) {
|
||||
|
||||
return Mono.defer(() -> {
|
||||
|
||||
ReactiveMongoTransactionObject mongoTransactionObject = extractMongoTransaction(status);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("About to abort transaction for session %s.",
|
||||
debugString(mongoTransactionObject.getSession())));
|
||||
}
|
||||
|
||||
return mongoTransactionObject.abortTransaction().onErrorResume(MongoException.class, ex -> {
|
||||
return Mono
|
||||
.error(new TransactionSystemException(String.format("Could not abort Mongo transaction for session %s.",
|
||||
debugString(mongoTransactionObject.getSession())), ex));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doSetRollbackOnly(org.springframework.transaction.reactive.TransactionSynchronizationManager, org.springframework.transaction.reactive.GenericReactiveTransaction)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Void> doSetRollbackOnly(TransactionSynchronizationManager synchronizationManager,
|
||||
GenericReactiveTransaction status) throws TransactionException {
|
||||
|
||||
return Mono.fromRunnable(() -> {
|
||||
ReactiveMongoTransactionObject transactionObject = extractMongoTransaction(status);
|
||||
transactionObject.getRequiredResourceHolder().setRollbackOnly();
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.reactive.AbstractReactiveTransactionManager#doCleanupAfterCompletion(org.springframework.transaction.reactive.TransactionSynchronizationManager, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Mono<Void> doCleanupAfterCompletion(TransactionSynchronizationManager synchronizationManager,
|
||||
Object transaction) {
|
||||
|
||||
Assert.isInstanceOf(ReactiveMongoTransactionObject.class, transaction,
|
||||
() -> String.format("Expected to find a %s but it turned out to be %s.", ReactiveMongoTransactionObject.class,
|
||||
transaction.getClass()));
|
||||
|
||||
return Mono.fromRunnable(() -> {
|
||||
ReactiveMongoTransactionObject mongoTransactionObject = (ReactiveMongoTransactionObject) transaction;
|
||||
|
||||
// Remove the connection holder from the thread.
|
||||
synchronizationManager.unbindResource(getRequiredDatabaseFactory());
|
||||
mongoTransactionObject.getRequiredResourceHolder().clear();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("About to release Session %s after transaction.",
|
||||
debugString(mongoTransactionObject.getSession())));
|
||||
}
|
||||
|
||||
mongoTransactionObject.closeSession();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ReactiveMongoDatabaseFactory} that this instance should manage transactions for.
|
||||
*
|
||||
* @param databaseFactory must not be {@literal null}.
|
||||
*/
|
||||
public void setDatabaseFactory(ReactiveMongoDatabaseFactory databaseFactory) {
|
||||
|
||||
Assert.notNull(databaseFactory, "DatabaseFactory must not be null!");
|
||||
this.databaseFactory = databaseFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link TransactionOptions} to be applied when starting transactions.
|
||||
*
|
||||
* @param options can be {@literal null}.
|
||||
*/
|
||||
public void setOptions(@Nullable TransactionOptions options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ReactiveMongoDatabaseFactory} that this instance manages transactions for.
|
||||
*
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
public ReactiveMongoDatabaseFactory getDatabaseFactory() {
|
||||
return databaseFactory;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
getRequiredDatabaseFactory();
|
||||
}
|
||||
|
||||
private Mono<ReactiveMongoResourceHolder> newResourceHolder(TransactionDefinition definition,
|
||||
ClientSessionOptions options) {
|
||||
|
||||
ReactiveMongoDatabaseFactory dbFactory = getRequiredDatabaseFactory();
|
||||
|
||||
return dbFactory.getSession(options).map(session -> new ReactiveMongoResourceHolder(session, dbFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalStateException if {@link #databaseFactory} is {@literal null}.
|
||||
*/
|
||||
private ReactiveMongoDatabaseFactory getRequiredDatabaseFactory() {
|
||||
|
||||
Assert.state(databaseFactory != null,
|
||||
"ReactiveMongoTransactionManager operates upon a ReactiveMongoDatabaseFactory. Did you forget to provide one? It's required.");
|
||||
|
||||
return databaseFactory;
|
||||
}
|
||||
|
||||
private static ReactiveMongoTransactionObject extractMongoTransaction(Object transaction) {
|
||||
|
||||
Assert.isInstanceOf(ReactiveMongoTransactionObject.class, transaction,
|
||||
() -> String.format("Expected to find a %s but it turned out to be %s.", ReactiveMongoTransactionObject.class,
|
||||
transaction.getClass()));
|
||||
|
||||
return (ReactiveMongoTransactionObject) transaction;
|
||||
}
|
||||
|
||||
private static ReactiveMongoTransactionObject extractMongoTransaction(GenericReactiveTransaction status) {
|
||||
|
||||
Assert.isInstanceOf(ReactiveMongoTransactionObject.class, status.getTransaction(),
|
||||
() -> String.format("Expected to find a %s but it turned out to be %s.", ReactiveMongoTransactionObject.class,
|
||||
status.getTransaction().getClass()));
|
||||
|
||||
return (ReactiveMongoTransactionObject) status.getTransaction();
|
||||
}
|
||||
|
||||
private static String debugString(@Nullable ClientSession session) {
|
||||
|
||||
if (session == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
String debugString = String.format("[%s@%s ", ClassUtils.getShortName(session.getClass()),
|
||||
Integer.toHexString(session.hashCode()));
|
||||
|
||||
try {
|
||||
if (session.getServerSession() != null) {
|
||||
debugString += String.format("id = %s, ", session.getServerSession().getIdentifier());
|
||||
debugString += String.format("causallyConsistent = %s, ", session.isCausallyConsistent());
|
||||
debugString += String.format("txActive = %s, ", session.hasActiveTransaction());
|
||||
debugString += String.format("txNumber = %d, ", session.getServerSession().getTransactionNumber());
|
||||
debugString += String.format("closed = %d, ", session.getServerSession().isClosed());
|
||||
debugString += String.format("clusterTime = %s", session.getClusterTime());
|
||||
} else {
|
||||
debugString += "id = n/a";
|
||||
debugString += String.format("causallyConsistent = %s, ", session.isCausallyConsistent());
|
||||
debugString += String.format("txActive = %s, ", session.hasActiveTransaction());
|
||||
debugString += String.format("clusterTime = %s", session.getClusterTime());
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
debugString += String.format("error = %s", e.getMessage());
|
||||
}
|
||||
|
||||
debugString += "]";
|
||||
|
||||
return debugString;
|
||||
}
|
||||
|
||||
/**
|
||||
* MongoDB specific transaction object, representing a {@link MongoResourceHolder}. Used as transaction object by
|
||||
* {@link ReactiveMongoTransactionManager}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 2.2
|
||||
* @see ReactiveMongoResourceHolder
|
||||
*/
|
||||
protected static class ReactiveMongoTransactionObject implements SmartTransactionObject {
|
||||
|
||||
private @Nullable ReactiveMongoResourceHolder resourceHolder;
|
||||
|
||||
ReactiveMongoTransactionObject(@Nullable ReactiveMongoResourceHolder resourceHolder) {
|
||||
this.resourceHolder = resourceHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link MongoResourceHolder}.
|
||||
*
|
||||
* @param resourceHolder can be {@literal null}.
|
||||
*/
|
||||
void setResourceHolder(@Nullable ReactiveMongoResourceHolder resourceHolder) {
|
||||
this.resourceHolder = resourceHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if a {@link MongoResourceHolder} is set.
|
||||
*/
|
||||
final boolean hasResourceHolder() {
|
||||
return resourceHolder != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a MongoDB transaction optionally given {@link TransactionOptions}.
|
||||
*
|
||||
* @param options can be {@literal null}
|
||||
*/
|
||||
void startTransaction(@Nullable TransactionOptions options) {
|
||||
|
||||
ClientSession session = getRequiredSession();
|
||||
if (options != null) {
|
||||
session.startTransaction(options);
|
||||
} else {
|
||||
session.startTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the transaction.
|
||||
*/
|
||||
public Mono<Void> commitTransaction() {
|
||||
return Mono.from(getRequiredSession().commitTransaction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback (abort) the transaction.
|
||||
*/
|
||||
public Mono<Void> abortTransaction() {
|
||||
return Mono.from(getRequiredSession().abortTransaction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a {@link ClientSession} without regard to its transactional state.
|
||||
*/
|
||||
void closeSession() {
|
||||
|
||||
ClientSession session = getRequiredSession();
|
||||
if (session.getServerSession() != null && !session.getServerSession().isClosed()) {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ClientSession getSession() {
|
||||
return resourceHolder != null ? resourceHolder.getSession() : null;
|
||||
}
|
||||
|
||||
private ReactiveMongoResourceHolder getRequiredResourceHolder() {
|
||||
|
||||
Assert.state(resourceHolder != null, "ReactiveMongoResourceHolder is required but not present. o_O");
|
||||
return resourceHolder;
|
||||
}
|
||||
|
||||
private ClientSession getRequiredSession() {
|
||||
|
||||
ClientSession session = getSession();
|
||||
Assert.state(session != null, "A Session is required but it turned out to be null.");
|
||||
return session;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.support.SmartTransactionObject#isRollbackOnly()
|
||||
*/
|
||||
@Override
|
||||
public boolean isRollbackOnly() {
|
||||
return this.resourceHolder != null && this.resourceHolder.isRollbackOnly();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.transaction.support.SmartTransactionObject#flush()
|
||||
*/
|
||||
@Override
|
||||
public void flush() {
|
||||
throw new UnsupportedOperationException("flush() not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,6 @@ public abstract class AbstractMongoClientConfiguration extends MongoConfiguratio
|
||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
|
||||
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext());
|
||||
converter.setCustomConversions(customConversions());
|
||||
converter.setCodecRegistryProvider(mongoDbFactory());
|
||||
|
||||
return converter;
|
||||
}
|
||||
|
||||
@@ -42,10 +42,8 @@ import com.mongodb.MongoClient;
|
||||
* @author Mark Paluch
|
||||
* @see MongoConfigurationSupport
|
||||
* @see AbstractMongoClientConfiguration
|
||||
* @deprecated since 2.2 in favor of {@link AbstractMongoClientConfiguration}.
|
||||
*/
|
||||
@Configuration
|
||||
@Deprecated
|
||||
public abstract class AbstractMongoConfiguration extends MongoConfigurationSupport {
|
||||
|
||||
/**
|
||||
@@ -113,7 +111,6 @@ public abstract class AbstractMongoConfiguration extends MongoConfigurationSuppo
|
||||
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory());
|
||||
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext());
|
||||
converter.setCustomConversions(customConversions());
|
||||
converter.setCodecRegistryProvider(mongoDbFactory());
|
||||
|
||||
return converter;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ public abstract class AbstractReactiveMongoConfiguration extends MongoConfigurat
|
||||
|
||||
MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mongoMappingContext());
|
||||
converter.setCustomConversions(customConversions());
|
||||
converter.setCodecRegistryProvider(reactiveMongoDbFactory());
|
||||
|
||||
return converter;
|
||||
}
|
||||
|
||||
@@ -42,21 +42,21 @@ public @interface EnableMongoAuditing {
|
||||
/**
|
||||
* Configures the {@link AuditorAware} bean to be used to lookup the current principal.
|
||||
*
|
||||
* @return empty {@link String} by default.
|
||||
* @return
|
||||
*/
|
||||
String auditorAwareRef() default "";
|
||||
|
||||
/**
|
||||
* Configures whether the creation and modification dates are set. Defaults to {@literal true}.
|
||||
*
|
||||
* @return {@literal true} by default.
|
||||
* @return
|
||||
*/
|
||||
boolean setDates() default true;
|
||||
|
||||
/**
|
||||
* Configures whether the entity shall be marked as modified on creation. Defaults to {@literal true}.
|
||||
*
|
||||
* @return {@literal true} by default.
|
||||
* @return
|
||||
*/
|
||||
boolean modifyOnCreate() default true;
|
||||
|
||||
@@ -64,7 +64,7 @@ public @interface EnableMongoAuditing {
|
||||
* Configures a {@link DateTimeProvider} bean name that allows customizing the {@link org.joda.time.DateTime} to be
|
||||
* used for setting creation and modification dates.
|
||||
*
|
||||
* @return empty {@link String} by default.
|
||||
* @return
|
||||
*/
|
||||
String dateTimeProviderRef() default "";
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.config.BeanComponentDefinitionBuilder;
|
||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
||||
@@ -101,6 +102,8 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
BeanDefinition conversionsDefinition = getCustomConversions(element, parserContext);
|
||||
String ctxRef = potentiallyCreateMappingContext(element, parserContext, conversionsDefinition, id);
|
||||
|
||||
createIsNewStrategyFactoryBeanDefinition(ctxRef, parserContext, element);
|
||||
|
||||
// Need a reference to a Mongo instance
|
||||
String dbFactoryRef = element.getAttribute("db-factory-ref");
|
||||
if (!StringUtils.hasText(dbFactoryRef)) {
|
||||
@@ -345,6 +348,20 @@ public class MappingMongoConverterParser implements BeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String createIsNewStrategyFactoryBeanDefinition(String mappingContextRef, ParserContext context,
|
||||
Element element) {
|
||||
|
||||
BeanDefinitionBuilder mappingContextStrategyFactoryBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(MappingContextIsNewStrategyFactory.class);
|
||||
mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
|
||||
|
||||
BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
|
||||
context.registerBeanComponent(
|
||||
builder.getComponent(mappingContextStrategyFactoryBuilder, IS_NEW_STRATEGY_FACTORY_BEAN_NAME));
|
||||
|
||||
return IS_NEW_STRATEGY_FACTORY_BEAN_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TypeFilter} that returns {@literal false} in case any of the given delegates matches.
|
||||
*
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.mongodb.config;
|
||||
import static org.springframework.data.config.ParsingUtils.*;
|
||||
import static org.springframework.data.mongodb.config.BeanNames.*;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -27,33 +26,25 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.auditing.config.IsNewAwareAuditingHandlerBeanDefinitionParser;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback;
|
||||
import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} to register a {@link AuditingEntityCallback} to transparently set auditing information
|
||||
* on an entity.
|
||||
* {@link BeanDefinitionParser} to register a {@link AuditingEventListener} to transparently set auditing information on
|
||||
* an entity.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private static boolean PROJECT_REACTOR_AVAILABLE = ClassUtils.isPresent("reactor.core.publisher.Mono",
|
||||
MongoAuditingRegistrar.class.getClassLoader());
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
|
||||
*/
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return AuditingEntityCallback.class;
|
||||
return AuditingEventListener.class;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -89,24 +80,7 @@ public class MongoAuditingBeanDefinitionParser extends AbstractSingleBeanDefinit
|
||||
mappingContextRef);
|
||||
parser.parse(element, parserContext);
|
||||
|
||||
AbstractBeanDefinition isNewAwareAuditingHandler = getObjectFactoryBeanDefinition(parser.getResolvedBeanName(),
|
||||
parserContext.extractSource(element));
|
||||
builder.addConstructorArgValue(isNewAwareAuditingHandler);
|
||||
|
||||
if (PROJECT_REACTOR_AVAILABLE) {
|
||||
registerReactiveAuditingEntityCallback(parserContext.getRegistry(), isNewAwareAuditingHandler,
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReactiveAuditingEntityCallback(BeanDefinitionRegistry registry,
|
||||
AbstractBeanDefinition isNewAwareAuditingHandler, @Nullable Object source) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class);
|
||||
|
||||
builder.addConstructorArgValue(isNewAwareAuditingHandler);
|
||||
builder.getRawBeanDefinition().setSource(source);
|
||||
|
||||
registry.registerBeanDefinition(ReactiveAuditingEntityCallback.class.getName(), builder.getBeanDefinition());
|
||||
builder.addConstructorArgValue(getObjectFactoryBeanDefinition(parser.getResolvedBeanName(),
|
||||
parserContext.extractSource(element)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,23 +32,17 @@ import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AuditingEntityCallback;
|
||||
import org.springframework.data.mongodb.core.mapping.event.ReactiveAuditingEntityCallback;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} to enable {@link EnableMongoAuditing} annotation.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
||||
|
||||
private static boolean PROJECT_REACTOR_AVAILABLE = ClassUtils.isPresent("reactor.core.publisher.Mono",
|
||||
MongoAuditingRegistrar.class.getClassLoader());
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport#getAnnotation()
|
||||
@@ -110,27 +104,12 @@ class MongoAuditingRegistrar extends AuditingBeanDefinitionRegistrarSupport {
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
|
||||
|
||||
BeanDefinitionBuilder listenerBeanDefinitionBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(AuditingEntityCallback.class);
|
||||
.rootBeanDefinition(AuditingEventListener.class);
|
||||
listenerBeanDefinitionBuilder
|
||||
.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
|
||||
|
||||
registerInfrastructureBeanWithId(listenerBeanDefinitionBuilder.getBeanDefinition(),
|
||||
AuditingEntityCallback.class.getName(), registry);
|
||||
|
||||
if (PROJECT_REACTOR_AVAILABLE) {
|
||||
registerReactiveAuditingEntityCallback(registry, auditingHandlerDefinition.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReactiveAuditingEntityCallback(BeanDefinitionRegistry registry, Object source) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ReactiveAuditingEntityCallback.class);
|
||||
|
||||
builder.addConstructorArgValue(ParsingUtils.getObjectFactoryBeanDefinition(getAuditingHandlerBeanName(), registry));
|
||||
builder.getRawBeanDefinition().setSource(source);
|
||||
|
||||
registerInfrastructureBeanWithId(builder.getBeanDefinition(), ReactiveAuditingEntityCallback.class.getName(),
|
||||
registry);
|
||||
AuditingEventListener.class.getName(), registry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@@ -27,12 +28,17 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.support.CachingIsNewStrategyFactory;
|
||||
import org.springframework.data.support.IsNewStrategyFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -81,15 +87,27 @@ public abstract class MongoConfigurationSupport {
|
||||
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
||||
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
|
||||
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
|
||||
mappingContext.setAutoIndexCreation(autoIndexCreation());
|
||||
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link MappingContextIsNewStrategyFactory} wrapped into a {@link CachingIsNewStrategyFactory}.
|
||||
*
|
||||
* @return
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@Bean
|
||||
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
|
||||
|
||||
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(
|
||||
new PersistentEntities(Arrays.<MappingContext<?, ?>> asList(new MappingContext[] { mongoMappingContext() }))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
|
||||
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
|
||||
* {@link MongoMappingContext}. Returns an empty {@link MongoCustomConversions} instance by default.
|
||||
* {@link #mongoMappingContext()}. Returns an empty {@link MongoCustomConversions} instance by default.
|
||||
*
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
@@ -172,16 +190,4 @@ public abstract class MongoConfigurationSupport {
|
||||
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
|
||||
: PropertyNameFieldNamingStrategy.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure whether to automatically create indices for domain types by deriving the
|
||||
* {@link org.springframework.data.mongodb.core.index.IndexDefinition} from the entity or not.
|
||||
*
|
||||
* @return {@literal true} by default. <br />
|
||||
* <strong>INFO</strong>: As of 3.x the default will be set to {@literal false}.
|
||||
* @since 2.2
|
||||
*/
|
||||
protected boolean autoIndexCreation() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -27,7 +26,6 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.MongoCredential;
|
||||
@@ -80,23 +78,12 @@ public class MongoCredentialPropertyEditor extends PropertyEditorSupport {
|
||||
|
||||
verifyUserNamePresent(userNameAndPassword);
|
||||
credentials.add(MongoCredential.createGSSAPICredential(userNameAndPassword[0]));
|
||||
} else if ("MONGODB-CR".equals(authMechanism)) {
|
||||
} else if (MongoCredential.MONGODB_CR_MECHANISM.equals(authMechanism)) {
|
||||
|
||||
verifyUsernameAndPasswordPresent(userNameAndPassword);
|
||||
verifyDatabasePresent(database);
|
||||
|
||||
Method createCRCredentialMethod = ReflectionUtils.findMethod(MongoCredential.class,
|
||||
"createMongoCRCredential", String.class, String.class, char[].class);
|
||||
|
||||
if (createCRCredentialMethod == null) {
|
||||
throw new IllegalArgumentException("MONGODB-CR is no longer supported.");
|
||||
}
|
||||
|
||||
MongoCredential credential = MongoCredential.class
|
||||
.cast(ReflectionUtils.invokeMethod(createCRCredentialMethod, null, userNameAndPassword[0], database,
|
||||
userNameAndPassword[1].toCharArray()));
|
||||
credentials.add(credential);
|
||||
|
||||
credentials.add(MongoCredential.createMongoCRCredential(userNameAndPassword[0], database,
|
||||
userNameAndPassword[1].toCharArray()));
|
||||
} else if (MongoCredential.MONGODB_X509_MECHANISM.equals(authMechanism)) {
|
||||
|
||||
verifyUserNamePresent(userNameAndPassword);
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.w3c.dom.Element;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
abstract class MongoParsingUtils {
|
||||
@@ -93,7 +92,6 @@ abstract class MongoParsingUtils {
|
||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "heartbeat-socket-timeout", "heartbeatSocketTimeout");
|
||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "ssl", "ssl");
|
||||
setPropertyReference(clientOptionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory");
|
||||
setPropertyReference(clientOptionsDefBuilder, optionsElement, "encryption-settings-ref", "autoEncryptionSettings");
|
||||
setPropertyValue(clientOptionsDefBuilder, optionsElement, "server-selection-timeout", "serverSelectionTimeout");
|
||||
|
||||
mongoClientBuilder.addPropertyValue("mongoClientOptions", clientOptionsDefBuilder.getBeanDefinition());
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.mongodb.bulk.BulkWriteResult;
|
||||
*
|
||||
* @author Tobias Trelle
|
||||
* @author Oliver Gierke
|
||||
* @author Minsu Kim
|
||||
* @since 1.9
|
||||
*/
|
||||
public interface BulkOperations {
|
||||
@@ -94,6 +93,7 @@ public interface BulkOperations {
|
||||
* Add a list of updates to the bulk operation. For each update request, all matching documents are updated.
|
||||
*
|
||||
* @param updates Update operations to perform.
|
||||
* @return The bulk operation.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations updateMulti(List<Pair<Query, Update>> updates);
|
||||
@@ -104,6 +104,7 @@ public interface BulkOperations {
|
||||
*
|
||||
* @param query Update criteria.
|
||||
* @param update Update operation to perform.
|
||||
* @return The bulk operation.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations upsert(Query query, Update update);
|
||||
@@ -113,6 +114,7 @@ public interface BulkOperations {
|
||||
* else an insert.
|
||||
*
|
||||
* @param updates Updates/insert operations to perform.
|
||||
* @return The bulk operation.
|
||||
* @return the current {@link BulkOperations} instance with the update added, will never be {@literal null}.
|
||||
*/
|
||||
BulkOperations upsert(List<Pair<Query, Update>> updates);
|
||||
@@ -133,29 +135,6 @@ public interface BulkOperations {
|
||||
*/
|
||||
BulkOperations remove(List<Query> removes);
|
||||
|
||||
/**
|
||||
* Add a single replace operation to the bulk operation.
|
||||
*
|
||||
* @param query Update criteria.
|
||||
* @param replacement the replacement document. Must not be {@literal null}.
|
||||
* @return the current {@link BulkOperations} instance with the replace added, will never be {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
default BulkOperations replaceOne(Query query, Object replacement) {
|
||||
return replaceOne(query, replacement, FindAndReplaceOptions.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single replace operation to the bulk operation.
|
||||
*
|
||||
* @param query Update criteria.
|
||||
* @param replacement the replacement document. Must not be {@literal null}.
|
||||
* @param options the {@link FindAndModifyOptions} holding additional information. Must not be {@literal null}.
|
||||
* @return the current {@link BulkOperations} instance with the replace added, will never be {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
BulkOperations replaceOne(Query query, Object replacement, FindAndReplaceOptions options);
|
||||
|
||||
/**
|
||||
* Execute all bulk operations using the default write concern.
|
||||
*
|
||||
|
||||
@@ -20,7 +20,6 @@ import lombok.EqualsAndHashCode;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
|
||||
import org.bson.BsonTimestamp;
|
||||
import org.bson.BsonValue;
|
||||
import org.bson.Document;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
@@ -85,19 +84,8 @@ public class ChangeStreamEvent<T> {
|
||||
@Nullable
|
||||
public Instant getTimestamp() {
|
||||
|
||||
return getBsonTimestamp() != null ? converter.getConversionService().convert(raw.getClusterTime(), Instant.class)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ChangeStreamDocument#getClusterTime() cluster time}.
|
||||
*
|
||||
* @return can be {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
@Nullable
|
||||
public BsonTimestamp getBsonTimestamp() {
|
||||
return raw != null ? raw.getClusterTime() : null;
|
||||
return raw != null && raw.getClusterTime() != null
|
||||
? converter.getConversionService().convert(raw.getClusterTime(), Instant.class) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,17 +21,12 @@ import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonTimestamp;
|
||||
import org.bson.BsonValue;
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.query.Collation;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.mongodb.client.model.changestream.ChangeStreamDocument;
|
||||
import com.mongodb.client.model.changestream.FullDocument;
|
||||
@@ -52,8 +47,7 @@ public class ChangeStreamOptions {
|
||||
private @Nullable BsonValue resumeToken;
|
||||
private @Nullable FullDocument fullDocumentLookup;
|
||||
private @Nullable Collation collation;
|
||||
private @Nullable Object resumeTimestamp;
|
||||
private Resume resume = Resume.UNDEFINED;
|
||||
private @Nullable Instant resumeTimestamp;
|
||||
|
||||
protected ChangeStreamOptions() {}
|
||||
|
||||
@@ -89,31 +83,7 @@ public class ChangeStreamOptions {
|
||||
* @return {@link Optional#empty()} if not set.
|
||||
*/
|
||||
public Optional<Instant> getResumeTimestamp() {
|
||||
return Optional.ofNullable(resumeTimestamp).map(timestamp -> asTimestampOfType(timestamp, Instant.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Optional#empty()} if not set.
|
||||
* @since 2.2
|
||||
*/
|
||||
public Optional<BsonTimestamp> getResumeBsonTimestamp() {
|
||||
return Optional.ofNullable(resumeTimestamp).map(timestamp -> asTimestampOfType(timestamp, BsonTimestamp.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the change stream should be started after the {@link #getResumeToken() token}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public boolean isStartAfter() {
|
||||
return Resume.START_AFTER.equals(resume);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the change stream should be resumed after the {@link #getResumeToken() token}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public boolean isResumeAfter() {
|
||||
return Resume.RESUME_AFTER.equals(resume);
|
||||
return Optional.ofNullable(resumeTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,48 +103,6 @@ public class ChangeStreamOptions {
|
||||
return new ChangeStreamOptionsBuilder();
|
||||
}
|
||||
|
||||
private static <T> T asTimestampOfType(Object timestamp, Class<T> targetType) {
|
||||
return targetType.cast(doGetTimestamp(timestamp, targetType));
|
||||
}
|
||||
|
||||
private static <T> Object doGetTimestamp(Object timestamp, Class<T> targetType) {
|
||||
|
||||
if (ClassUtils.isAssignableValue(targetType, timestamp)) {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
if (timestamp instanceof Instant) {
|
||||
return new BsonTimestamp((int) ((Instant) timestamp).getEpochSecond(), 0);
|
||||
}
|
||||
|
||||
if (timestamp instanceof BsonTimestamp) {
|
||||
return Instant.ofEpochSecond(((BsonTimestamp) timestamp).getTime());
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"o_O that should actually not happen. The timestamp should be an Instant or a BsonTimestamp but was "
|
||||
+ ObjectUtils.nullSafeClassName(timestamp));
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
*/
|
||||
enum Resume {
|
||||
|
||||
UNDEFINED,
|
||||
|
||||
/**
|
||||
* @see com.mongodb.client.ChangeStreamIterable#startAfter(BsonDocument)
|
||||
*/
|
||||
START_AFTER,
|
||||
|
||||
/**
|
||||
* @see com.mongodb.client.ChangeStreamIterable#resumeAfter(BsonDocument)
|
||||
*/
|
||||
RESUME_AFTER
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for creating {@link ChangeStreamOptions}.
|
||||
*
|
||||
@@ -187,8 +115,7 @@ public class ChangeStreamOptions {
|
||||
private @Nullable BsonValue resumeToken;
|
||||
private @Nullable FullDocument fullDocumentLookup;
|
||||
private @Nullable Collation collation;
|
||||
private @Nullable Object resumeTimestamp;
|
||||
private Resume resume = Resume.UNDEFINED;
|
||||
private @Nullable Instant resumeTimestamp;
|
||||
|
||||
private ChangeStreamOptionsBuilder() {}
|
||||
|
||||
@@ -256,11 +183,6 @@ public class ChangeStreamOptions {
|
||||
Assert.notNull(resumeToken, "ResumeToken must not be null!");
|
||||
|
||||
this.resumeToken = resumeToken;
|
||||
|
||||
if (this.resume == Resume.UNDEFINED) {
|
||||
this.resume = Resume.RESUME_AFTER;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -302,51 +224,6 @@ public class ChangeStreamOptions {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cluster time to resume from.
|
||||
*
|
||||
* @param resumeTimestamp must not be {@literal null}.
|
||||
* @return this.
|
||||
* @since 2.2
|
||||
*/
|
||||
public ChangeStreamOptionsBuilder resumeAt(BsonTimestamp resumeTimestamp) {
|
||||
|
||||
Assert.notNull(resumeTimestamp, "ResumeTimestamp must not be null!");
|
||||
|
||||
this.resumeTimestamp = resumeTimestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resume token after which to continue emitting notifications.
|
||||
*
|
||||
* @param resumeToken must not be {@literal null}.
|
||||
* @return this.
|
||||
* @since 2.2
|
||||
*/
|
||||
public ChangeStreamOptionsBuilder resumeAfter(BsonValue resumeToken) {
|
||||
|
||||
resumeToken(resumeToken);
|
||||
this.resume = Resume.RESUME_AFTER;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resume token after which to start emitting notifications.
|
||||
*
|
||||
* @param resumeToken must not be {@literal null}.
|
||||
* @return this.
|
||||
* @since 2.2
|
||||
*/
|
||||
public ChangeStreamOptionsBuilder startAfter(BsonValue resumeToken) {
|
||||
|
||||
resumeToken(resumeToken);
|
||||
this.resume = Resume.START_AFTER;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the built {@link ChangeStreamOptions}
|
||||
*/
|
||||
@@ -354,12 +231,11 @@ public class ChangeStreamOptions {
|
||||
|
||||
ChangeStreamOptions options = new ChangeStreamOptions();
|
||||
|
||||
options.filter = this.filter;
|
||||
options.resumeToken = this.resumeToken;
|
||||
options.fullDocumentLookup = this.fullDocumentLookup;
|
||||
options.collation = this.collation;
|
||||
options.resumeTimestamp = this.resumeTimestamp;
|
||||
options.resume = this.resume;
|
||||
options.filter = filter;
|
||||
options.resumeToken = resumeToken;
|
||||
options.fullDocumentLookup = fullDocumentLookup;
|
||||
options.collation = collation;
|
||||
options.resumeTimestamp = resumeTimestamp;
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.mongodb.client.MongoCollection;
|
||||
* @author Grame Rocher
|
||||
* @author Oliver Gierke
|
||||
* @author John Brisbin
|
||||
* @author Christoph Strobl
|
||||
* @auhtor Christoph Strobl
|
||||
* @since 1.0
|
||||
*/
|
||||
public interface CollectionCallback<T> {
|
||||
|
||||
@@ -95,7 +95,7 @@ public class CollectionOptions {
|
||||
|
||||
/**
|
||||
* Create new {@link CollectionOptions} with already given settings and capped set to {@literal true}. <br />
|
||||
* <strong>NOTE</strong> Using capped collections requires defining {@link #size(long)}.
|
||||
* <strong>NOTE</strong> Using capped collections requires defining {@link #size(int)}.
|
||||
*
|
||||
* @return new {@link CollectionOptions}.
|
||||
* @since 2.0
|
||||
|
||||
@@ -15,15 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.ReadPreference;
|
||||
import com.mongodb.client.FindIterable;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
|
||||
/**
|
||||
* Simple callback interface to allow customization of a {@link FindIterable}.
|
||||
@@ -31,53 +25,12 @@ import com.mongodb.client.MongoCollection;
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public interface CursorPreparer extends ReadPreferenceAware {
|
||||
|
||||
/**
|
||||
* Default {@link CursorPreparer} just passing on the given {@link FindIterable}.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
CursorPreparer NO_OP_PREPARER = (iterable -> iterable);
|
||||
public interface CursorPreparer {
|
||||
|
||||
/**
|
||||
* Prepare the given cursor (apply limits, skips and so on). Returns the prepared cursor.
|
||||
*
|
||||
* @param iterable must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @param cursor
|
||||
*/
|
||||
FindIterable<Document> prepare(FindIterable<Document> iterable);
|
||||
|
||||
/**
|
||||
* Apply query specific settings to {@link MongoCollection} and initate a find operation returning a
|
||||
* {@link FindIterable} via the given {@link Function find} function.
|
||||
*
|
||||
* @param collection must not be {@literal null}.
|
||||
* @param find must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @throws IllegalArgumentException if one of the required arguments is {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
default FindIterable<Document> initiateFind(MongoCollection<Document> collection,
|
||||
Function<MongoCollection<Document>, FindIterable<Document>> find) {
|
||||
|
||||
Assert.notNull(collection, "Collection must not be null!");
|
||||
Assert.notNull(find, "Find function must not be null!");
|
||||
|
||||
if (hasReadPreference()) {
|
||||
collection = collection.withReadPreference(getReadPreference());
|
||||
}
|
||||
|
||||
return prepare(find.apply(collection));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link ReadPreference} to apply or {@literal null} if none defined.
|
||||
* @since 2.2
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
default ReadPreference getReadPreference() {
|
||||
return null;
|
||||
}
|
||||
FindIterable<Document> prepare(FindIterable<Document> cursor);
|
||||
}
|
||||
|
||||
@@ -26,31 +26,30 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
import org.springframework.data.mongodb.core.convert.QueryMapper;
|
||||
import org.springframework.data.mongodb.core.convert.UpdateMapper;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveCallback;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent;
|
||||
import org.springframework.data.mongodb.core.query.Collation;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BulkWriteException;
|
||||
import com.mongodb.WriteConcern;
|
||||
import com.mongodb.bulk.BulkWriteResult;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.model.*;
|
||||
import com.mongodb.client.model.BulkWriteOptions;
|
||||
import com.mongodb.client.model.DeleteManyModel;
|
||||
import com.mongodb.client.model.DeleteOneModel;
|
||||
import com.mongodb.client.model.DeleteOptions;
|
||||
import com.mongodb.client.model.InsertOneModel;
|
||||
import com.mongodb.client.model.UpdateManyModel;
|
||||
import com.mongodb.client.model.UpdateOneModel;
|
||||
import com.mongodb.client.model.UpdateOptions;
|
||||
import com.mongodb.client.model.WriteModel;
|
||||
|
||||
/**
|
||||
* Default implementation for {@link BulkOperations}.
|
||||
@@ -59,8 +58,6 @@ import com.mongodb.client.model.*;
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Minsu Kim
|
||||
* @author Jens Schauder
|
||||
* @author Michail Nikolaev
|
||||
* @since 1.9
|
||||
*/
|
||||
@@ -69,7 +66,7 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
private final MongoOperations mongoOperations;
|
||||
private final String collectionName;
|
||||
private final BulkOperationContext bulkOperationContext;
|
||||
private final List<SourceAwareWriteModelHolder> models = new ArrayList<>();
|
||||
private final List<WriteModel<Document>> models = new ArrayList<>();
|
||||
|
||||
private PersistenceExceptionTranslator exceptionTranslator;
|
||||
private @Nullable WriteConcern defaultWriteConcern;
|
||||
@@ -126,9 +123,16 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
|
||||
Assert.notNull(document, "Document must not be null!");
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<>(document, collectionName));
|
||||
Object source = maybeInvokeBeforeConvertCallback(document);
|
||||
addModel(source, new InsertOneModel<>(getMappedObject(source)));
|
||||
if (document instanceof Document) {
|
||||
|
||||
models.add(new InsertOneModel<>((Document) document));
|
||||
return this;
|
||||
}
|
||||
|
||||
Document sink = new Document();
|
||||
mongoOperations.getConverter().write(document, sink);
|
||||
|
||||
models.add(new InsertOneModel<>(sink));
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -242,7 +246,7 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
DeleteOptions deleteOptions = new DeleteOptions();
|
||||
query.getCollation().map(Collation::toMongoCollation).ifPresent(deleteOptions::collation);
|
||||
|
||||
addModel(query, new DeleteManyModel<>(query.getQueryObject(), deleteOptions));
|
||||
models.add(new DeleteManyModel<>(query.getQueryObject(), deleteOptions));
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -263,29 +267,6 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#replaceOne(org.springframework.data.mongodb.core.query.Query, java.lang.Object, org.springframework.data.mongodb.core.FindAndReplaceOptions)
|
||||
*/
|
||||
@Override
|
||||
public BulkOperations replaceOne(Query query, Object replacement, FindAndReplaceOptions options) {
|
||||
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
Assert.notNull(replacement, "Replacement must not be null!");
|
||||
Assert.notNull(options, "Options must not be null!");
|
||||
|
||||
ReplaceOptions replaceOptions = new ReplaceOptions();
|
||||
replaceOptions.upsert(options.isUpsert());
|
||||
query.getCollation().map(Collation::toMongoCollation).ifPresent(replaceOptions::collation);
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<>(replacement, collectionName));
|
||||
Object source = maybeInvokeBeforeConvertCallback(replacement);
|
||||
addModel(source,
|
||||
new ReplaceOneModel<>(getMappedQuery(query.getQueryObject()), getMappedObject(source), replaceOptions));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.BulkOperations#executeBulk()
|
||||
@@ -295,48 +276,18 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
|
||||
try {
|
||||
|
||||
com.mongodb.bulk.BulkWriteResult result = mongoOperations.execute(collectionName, this::bulkWriteTo);
|
||||
return mongoOperations.execute(collectionName, collection -> {
|
||||
|
||||
Assert.state(result != null, "Result must not be null.");
|
||||
|
||||
models.forEach(this::maybeEmitAfterSaveEvent);
|
||||
|
||||
return result;
|
||||
if (defaultWriteConcern != null) {
|
||||
collection = collection.withWriteConcern(defaultWriteConcern);
|
||||
}
|
||||
return collection.bulkWrite(models.stream().map(this::mapWriteModel).collect(Collectors.toList()), bulkOptions);
|
||||
});
|
||||
} finally {
|
||||
this.bulkOptions = getBulkWriteOptions(bulkOperationContext.getBulkMode());
|
||||
}
|
||||
}
|
||||
|
||||
private BulkWriteResult bulkWriteTo(MongoCollection<Document> collection) {
|
||||
|
||||
if (defaultWriteConcern != null) {
|
||||
collection = collection.withWriteConcern(defaultWriteConcern);
|
||||
}
|
||||
|
||||
return collection.bulkWrite( //
|
||||
models.stream() //
|
||||
.map(this::extractAndMapWriteModel) //
|
||||
.collect(Collectors.toList()), //
|
||||
bulkOptions);
|
||||
}
|
||||
|
||||
private WriteModel<Document> extractAndMapWriteModel(SourceAwareWriteModelHolder it) {
|
||||
|
||||
maybeEmitBeforeSaveEvent(it);
|
||||
|
||||
if (it.getModel() instanceof InsertOneModel) {
|
||||
|
||||
Document target = ((InsertOneModel<Document>) it.getModel()).getDocument();
|
||||
maybeInvokeBeforeSaveCallback(it.getSource(), target);
|
||||
} else if (it.getModel() instanceof ReplaceOneModel) {
|
||||
|
||||
Document target = ((ReplaceOneModel<Document>) it.getModel()).getReplacement();
|
||||
maybeInvokeBeforeSaveCallback(it.getSource(), target);
|
||||
}
|
||||
|
||||
return mapWriteModel(it.getModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs update and upsert bulk operations.
|
||||
*
|
||||
@@ -351,12 +302,14 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
Assert.notNull(query, "Query must not be null!");
|
||||
Assert.notNull(update, "Update must not be null!");
|
||||
|
||||
UpdateOptions options = computeUpdateOptions(query, update, upsert);
|
||||
UpdateOptions options = new UpdateOptions();
|
||||
options.upsert(upsert);
|
||||
query.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation);
|
||||
|
||||
if (multi) {
|
||||
addModel(update, new UpdateManyModel<>(query.getQueryObject(), update.getUpdateObject(), options));
|
||||
models.add(new UpdateManyModel<>(query.getQueryObject(), update.getUpdateObject(), options));
|
||||
} else {
|
||||
addModel(update, new UpdateOneModel<>(query.getQueryObject(), update.getUpdateObject(), options));
|
||||
models.add(new UpdateOneModel<>(query.getQueryObject(), update.getUpdateObject(), options));
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -405,76 +358,6 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
return bulkOperationContext.getQueryMapper().getMappedObject(query, bulkOperationContext.getEntity());
|
||||
}
|
||||
|
||||
private Document getMappedObject(Object source) {
|
||||
|
||||
if (source instanceof Document) {
|
||||
return (Document) source;
|
||||
}
|
||||
|
||||
Document sink = new Document();
|
||||
|
||||
mongoOperations.getConverter().write(source, sink);
|
||||
return sink;
|
||||
}
|
||||
|
||||
private void addModel(Object source, WriteModel<Document> model) {
|
||||
models.add(new SourceAwareWriteModelHolder(source, model));
|
||||
}
|
||||
|
||||
private void maybeEmitBeforeSaveEvent(SourceAwareWriteModelHolder it) {
|
||||
|
||||
if (it.getModel() instanceof InsertOneModel) {
|
||||
|
||||
Document target = ((InsertOneModel<Document>) it.getModel()).getDocument();
|
||||
maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), target, collectionName));
|
||||
} else if (it.getModel() instanceof ReplaceOneModel) {
|
||||
|
||||
Document target = ((ReplaceOneModel<Document>) it.getModel()).getReplacement();
|
||||
maybeEmitEvent(new BeforeSaveEvent<>(it.getSource(), target, collectionName));
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeEmitAfterSaveEvent(SourceAwareWriteModelHolder it) {
|
||||
|
||||
if (it.getModel() instanceof InsertOneModel) {
|
||||
|
||||
Document target = ((InsertOneModel<Document>) it.getModel()).getDocument();
|
||||
maybeEmitEvent(new AfterSaveEvent<>(it.getSource(), target, collectionName));
|
||||
} else if (it.getModel() instanceof ReplaceOneModel) {
|
||||
|
||||
Document target = ((ReplaceOneModel<Document>) it.getModel()).getReplacement();
|
||||
maybeEmitEvent(new AfterSaveEvent<>(it.getSource(), target, collectionName));
|
||||
}
|
||||
}
|
||||
|
||||
private <E extends MongoMappingEvent<T>, T> E maybeEmitEvent(E event) {
|
||||
|
||||
if (null != bulkOperationContext.getEventPublisher()) {
|
||||
bulkOperationContext.getEventPublisher().publishEvent(event);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
private Object maybeInvokeBeforeConvertCallback(Object value) {
|
||||
|
||||
if (bulkOperationContext.getEntityCallbacks() == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return bulkOperationContext.getEntityCallbacks().callback(BeforeConvertCallback.class, value, collectionName);
|
||||
}
|
||||
|
||||
private Object maybeInvokeBeforeSaveCallback(Object value, Document mappedDocument) {
|
||||
|
||||
if (bulkOperationContext.getEntityCallbacks() == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return bulkOperationContext.getEntityCallbacks().callback(BeforeSaveCallback.class, value, mappedDocument,
|
||||
collectionName);
|
||||
}
|
||||
|
||||
private static BulkWriteOptions getBulkWriteOptions(BulkMode bulkMode) {
|
||||
|
||||
BulkWriteOptions options = new BulkWriteOptions();
|
||||
@@ -489,29 +372,6 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
throw new IllegalStateException("BulkMode was null!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param filterQuery The {@link Query} to read a potential {@link Collation} from. Must not be {@literal null}.
|
||||
* @param update The {@link Update} to apply
|
||||
* @param upsert flag to indicate if document should be upserted.
|
||||
* @return new instance of {@link UpdateOptions}.
|
||||
*/
|
||||
private static UpdateOptions computeUpdateOptions(Query filterQuery, UpdateDefinition update, boolean upsert) {
|
||||
|
||||
UpdateOptions options = new UpdateOptions();
|
||||
options.upsert(upsert);
|
||||
|
||||
if (update.hasArrayFilters()) {
|
||||
List<Document> list = new ArrayList<>(update.getArrayFilters().size());
|
||||
for (ArrayFilter arrayFilter : update.getArrayFilters()) {
|
||||
list.add(arrayFilter.asDocument());
|
||||
}
|
||||
options.arrayFilters(list);
|
||||
}
|
||||
|
||||
filterQuery.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation);
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BulkOperationContext} holds information about
|
||||
* {@link org.springframework.data.mongodb.core.BulkOperations.BulkMode} the entity in use as well as references to
|
||||
@@ -527,20 +387,5 @@ class DefaultBulkOperations implements BulkOperations {
|
||||
@NonNull Optional<? extends MongoPersistentEntity<?>> entity;
|
||||
@NonNull QueryMapper queryMapper;
|
||||
@NonNull UpdateMapper updateMapper;
|
||||
ApplicationEventPublisher eventPublisher;
|
||||
EntityCallbacks entityCallbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value object chaining together an actual source with its {@link WriteModel} representation.
|
||||
*
|
||||
* @since 2.2
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Value
|
||||
private static class SourceAwareWriteModelHolder {
|
||||
|
||||
Object source;
|
||||
WriteModel<Document> model;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,15 +120,19 @@ public class DefaultIndexOperations implements IndexOperations {
|
||||
|
||||
return execute(collection -> {
|
||||
|
||||
MongoPersistentEntity<?> entity = lookupPersistentEntity(type, collectionName);
|
||||
Document indexOptions = indexDefinition.getIndexOptions();
|
||||
|
||||
IndexOptions indexOptions = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
|
||||
IndexOptions ops = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
|
||||
|
||||
indexOptions = addPartialFilterIfPresent(indexOptions, indexDefinition.getIndexOptions(), entity);
|
||||
indexOptions = addDefaultCollationIfRequired(indexOptions, entity);
|
||||
if (indexOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
|
||||
|
||||
Document mappedKeys = mapper.getMappedSort(indexDefinition.getIndexKeys(), entity);
|
||||
return collection.createIndex(mappedKeys, indexOptions);
|
||||
Assert.isInstanceOf(Document.class, indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
|
||||
|
||||
ops.partialFilterExpression(mapper.getMappedObject((Document) indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY),
|
||||
lookupPersistentEntity(type, collectionName)));
|
||||
}
|
||||
|
||||
return collection.createIndex(indexDefinition.getIndexKeys(), ops);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -188,7 +192,7 @@ public class DefaultIndexOperations implements IndexOperations {
|
||||
|
||||
private List<IndexInfo> getIndexData(MongoCursor<Document> cursor) {
|
||||
|
||||
List<IndexInfo> indexInfoList = new ArrayList<>();
|
||||
List<IndexInfo> indexInfoList = new ArrayList<IndexInfo>();
|
||||
|
||||
while (cursor.hasNext()) {
|
||||
|
||||
@@ -213,25 +217,4 @@ public class DefaultIndexOperations implements IndexOperations {
|
||||
|
||||
return mongoOperations.execute(collectionName, callback);
|
||||
}
|
||||
|
||||
private IndexOptions addPartialFilterIfPresent(IndexOptions ops, Document sourceOptions,
|
||||
@Nullable MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (!sourceOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
|
||||
return ops;
|
||||
}
|
||||
|
||||
Assert.isInstanceOf(Document.class, sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
|
||||
return ops.partialFilterExpression(
|
||||
mapper.getMappedSort((Document) sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY), entity));
|
||||
}
|
||||
|
||||
private static IndexOptions addDefaultCollationIfRequired(IndexOptions ops, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (ops.getCollation() != null || entity == null || !entity.hasCollation()) {
|
||||
return ops;
|
||||
}
|
||||
|
||||
return ops.collation(entity.getCollation().toMongoCollation());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,16 +94,23 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
|
||||
|
||||
return mongoOperations.execute(collectionName, collection -> {
|
||||
|
||||
MongoPersistentEntity<?> entity = type
|
||||
.map(val -> (MongoPersistentEntity) queryMapper.getMappingContext().getRequiredPersistentEntity(val))
|
||||
.orElseGet(() -> lookupPersistentEntity(collectionName));
|
||||
Document indexOptions = indexDefinition.getIndexOptions();
|
||||
|
||||
IndexOptions indexOptions = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
|
||||
IndexOptions ops = IndexConverters.indexDefinitionToIndexOptionsConverter().convert(indexDefinition);
|
||||
|
||||
indexOptions = addPartialFilterIfPresent(indexOptions, indexDefinition.getIndexOptions(), entity);
|
||||
indexOptions = addDefaultCollationIfRequired(indexOptions, entity);
|
||||
if (indexOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
|
||||
|
||||
return collection.createIndex(indexDefinition.getIndexKeys(), indexOptions);
|
||||
Assert.isInstanceOf(Document.class, indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
|
||||
|
||||
MongoPersistentEntity<?> entity = type
|
||||
.map(val -> (MongoPersistentEntity) queryMapper.getMappingContext().getRequiredPersistentEntity(val))
|
||||
.orElseGet(() -> lookupPersistentEntity(collectionName));
|
||||
|
||||
ops = ops.partialFilterExpression(
|
||||
queryMapper.getMappedObject(indexOptions.get(PARTIAL_FILTER_EXPRESSION_KEY, Document.class), entity));
|
||||
}
|
||||
|
||||
return collection.createIndex(indexDefinition.getIndexKeys(), ops);
|
||||
|
||||
}).next();
|
||||
}
|
||||
@@ -119,24 +126,21 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.index.ReactiveIndexOperations#dropIndex(java.lang.String)
|
||||
*/
|
||||
public Mono<Void> dropIndex(final String name) {
|
||||
return mongoOperations.execute(collectionName, collection -> collection.dropIndex(name)).then();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.index.ReactiveIndexOperations#dropAllIndexes()
|
||||
*/
|
||||
public Mono<Void> dropAllIndexes() {
|
||||
return dropIndex("*");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.index.ReactiveIndexOperations#getIndexInfo()
|
||||
*/
|
||||
public Flux<IndexInfo> getIndexInfo() {
|
||||
@@ -144,25 +148,4 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
|
||||
return mongoOperations.execute(collectionName, collection -> collection.listIndexes(Document.class)) //
|
||||
.map(IndexConverters.documentToIndexInfoConverter()::convert);
|
||||
}
|
||||
|
||||
private IndexOptions addPartialFilterIfPresent(IndexOptions ops, Document sourceOptions,
|
||||
@Nullable MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (!sourceOptions.containsKey(PARTIAL_FILTER_EXPRESSION_KEY)) {
|
||||
return ops;
|
||||
}
|
||||
|
||||
Assert.isInstanceOf(Document.class, sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY));
|
||||
return ops.partialFilterExpression(
|
||||
queryMapper.getMappedObject((Document) sourceOptions.get(PARTIAL_FILTER_EXPRESSION_KEY), entity));
|
||||
}
|
||||
|
||||
private static IndexOptions addDefaultCollationIfRequired(IndexOptions ops, MongoPersistentEntity<?> entity) {
|
||||
|
||||
if (ops.getCollation() != null || entity == null || !entity.hasCollation()) {
|
||||
return ops;
|
||||
}
|
||||
|
||||
return ops.collation(entity.getCollation().toMongoCollation());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,15 +42,13 @@ import com.mongodb.MongoException;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ScriptOperations} capable of saving and executing {@link ExecutableMongoScript}.
|
||||
* Default implementation of {@link ScriptOperations} capable of saving and executing {@link ServerSideJavaScript}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 1.7
|
||||
* @deprecated since 2.2. The {@code eval} command has been removed in MongoDB Server 4.2.0.
|
||||
*/
|
||||
@Deprecated
|
||||
class DefaultScriptOperations implements ScriptOperations {
|
||||
|
||||
private static final String SCRIPT_COLLECTION_NAME = "system.js";
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.mongodb.MongoException;
|
||||
/**
|
||||
* An interface used by {@link MongoTemplate} for processing documents returned from a MongoDB query on a per-document
|
||||
* basis. Implementations of this interface perform the actual work of prcoessing each document but don't need to worry
|
||||
* about exception handling. {@link MongoException}s will be caught and translated by the calling MongoTemplate An
|
||||
* about exception handling. {@MongoException}s will be caught and translated by the calling MongoTemplate An
|
||||
* DocumentCallbackHandler is typically stateful: It keeps the result state within the object, to be available later for
|
||||
* later inspection.
|
||||
*
|
||||
|
||||
@@ -21,14 +21,12 @@ import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.mapping.IdentifierAccessor;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
@@ -36,15 +34,15 @@ import org.springframework.data.mongodb.core.convert.MongoWriter;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.data.mongodb.core.query.Collation;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.mongodb.util.JSONParseException;
|
||||
|
||||
/**
|
||||
* Common operations performed on an entity in the context of it's mapping metadata.
|
||||
*
|
||||
@@ -66,7 +64,7 @@ class EntityOperations {
|
||||
* Creates a new {@link Entity} for the given bean.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return new instance of {@link Entity}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <T> Entity<T> forEntity(T entity) {
|
||||
@@ -89,7 +87,7 @@ class EntityOperations {
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param conversionService must not be {@literal null}.
|
||||
* @return new instance of {@link AdaptibleEntity}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public <T> AdaptibleEntity<T> forEntity(T entity, ConversionService conversionService) {
|
||||
@@ -108,10 +106,6 @@ class EntityOperations {
|
||||
return AdaptibleMappedEntity.of(entity, context, conversionService);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityClass should not be null.
|
||||
* @return the {@link MongoPersistentEntity#getCollection() collection name}.
|
||||
*/
|
||||
public String determineCollectionName(@Nullable Class<?> entityClass) {
|
||||
|
||||
if (entityClass == null) {
|
||||
@@ -142,7 +136,7 @@ class EntityOperations {
|
||||
* {@code _id} if no identifier property can be found.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public String getIdPropertyName(Class<?> type) {
|
||||
|
||||
@@ -157,59 +151,15 @@ class EntityOperations {
|
||||
return ID_FIELD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name used for {@code $geoNear.distanceField} avoiding clashes with potentially existing properties.
|
||||
*
|
||||
* @param domainType must not be {@literal null}.
|
||||
* @return the name of the distanceField to use. {@literal dis} by default.
|
||||
* @since 2.2
|
||||
*/
|
||||
public String nearQueryDistanceFieldName(Class<?> domainType) {
|
||||
|
||||
MongoPersistentEntity<?> persistentEntity = context.getPersistentEntity(domainType);
|
||||
if (persistentEntity == null || persistentEntity.getPersistentProperty("dis") == null) {
|
||||
return "dis";
|
||||
}
|
||||
|
||||
String distanceFieldName = "calculated-distance";
|
||||
int counter = 0;
|
||||
while (persistentEntity.getPersistentProperty(distanceFieldName) != null) {
|
||||
distanceFieldName += "-" + (counter++);
|
||||
}
|
||||
|
||||
return distanceFieldName;
|
||||
}
|
||||
|
||||
private static Document parse(String source) {
|
||||
|
||||
try {
|
||||
return Document.parse(source);
|
||||
} catch (org.bson.json.JsonParseException o_O) {
|
||||
} catch (JSONParseException | org.bson.json.JsonParseException o_O) {
|
||||
throw new MappingException("Could not parse given String to save into a JSON document!", o_O);
|
||||
} catch (RuntimeException o_O) {
|
||||
|
||||
// legacy 3.x exception
|
||||
if (ClassUtils.matchesTypeName(o_O.getClass(), "JSONParseException")) {
|
||||
throw new MappingException("Could not parse given String to save into a JSON document!", o_O);
|
||||
}
|
||||
throw o_O;
|
||||
}
|
||||
}
|
||||
|
||||
public <T> TypedOperations<T> forType(@Nullable Class<T> entityClass) {
|
||||
|
||||
if (entityClass != null) {
|
||||
|
||||
MongoPersistentEntity<?> entity = context.getPersistentEntity(entityClass);
|
||||
|
||||
if (entity != null) {
|
||||
return new TypedEntityOperations(entity);
|
||||
}
|
||||
|
||||
}
|
||||
return UntypedOperations.instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* A representation of information about an entity.
|
||||
*
|
||||
@@ -239,16 +189,6 @@ class EntityOperations {
|
||||
*/
|
||||
Query getByIdQuery();
|
||||
|
||||
/**
|
||||
* Returns the {@link Query} to remove an entity by its {@literal id} and if applicable {@literal version}.
|
||||
*
|
||||
* @return the {@link Query} to use for removing the entity. Never {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
default Query getRemoveByQuery() {
|
||||
return isVersionedEntity() ? getQueryForVersion() : getByIdQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Query} to find the entity in its current version.
|
||||
*
|
||||
@@ -279,11 +219,9 @@ class EntityOperations {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the version if the entity {@link #isVersionedEntity() has a version property}.
|
||||
* Returns the value of the version if the entity has a version property, {@literal null} otherwise.
|
||||
*
|
||||
* @return the entity version. Can be {@literal null}.
|
||||
* @throws IllegalStateException if the entity does not define a {@literal version} property. Make sure to check
|
||||
* {@link #isVersionedEntity()}.
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
Object getVersion();
|
||||
@@ -297,7 +235,7 @@ class EntityOperations {
|
||||
|
||||
/**
|
||||
* Returns whether the entity is considered to be new.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* @since 2.1.2
|
||||
*/
|
||||
@@ -339,8 +277,8 @@ class EntityOperations {
|
||||
/**
|
||||
* Returns the current version value if the entity has a version property.
|
||||
*
|
||||
* @return the current version or {@literal null} in case it's uninitialized.
|
||||
* @throws IllegalStateException if the entity does not define a {@literal version} property.
|
||||
* @return the current version or {@literal null} in case it's uninitialized or the entity doesn't expose a version
|
||||
* property.
|
||||
*/
|
||||
@Nullable
|
||||
Number getVersion();
|
||||
@@ -448,7 +386,7 @@ class EntityOperations {
|
||||
return map;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.EntityOperations.Entity#isNew()
|
||||
*/
|
||||
@@ -542,10 +480,10 @@ class EntityOperations {
|
||||
public Query getQueryForVersion() {
|
||||
|
||||
MongoPersistentProperty idProperty = entity.getRequiredIdProperty();
|
||||
MongoPersistentProperty versionProperty = entity.getRequiredVersionProperty();
|
||||
MongoPersistentProperty property = entity.getRequiredVersionProperty();
|
||||
|
||||
return new Query(Criteria.where(idProperty.getName()).is(getId())//
|
||||
.and(versionProperty.getName()).is(getVersion()));
|
||||
.and(property.getName()).is(getVersion()));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -619,7 +557,7 @@ class EntityOperations {
|
||||
return propertyAccessor.getBean();
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.EntityOperations.Entity#isNew()
|
||||
*/
|
||||
@@ -729,102 +667,4 @@ class EntityOperations {
|
||||
return propertyAccessor.getBean();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-specific operations abstraction.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @param <T>
|
||||
* @since 2.2
|
||||
*/
|
||||
interface TypedOperations<T> {
|
||||
|
||||
/**
|
||||
* Return the optional {@link Collation} for the underlying entity.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Optional<Collation> getCollation();
|
||||
|
||||
/**
|
||||
* Return the optional {@link Collation} from the given {@link Query} and fall back to the collation configured for
|
||||
* the underlying entity.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Optional<Collation> getCollation(Query query);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TypedOperations} for generic entities that are not represented with {@link PersistentEntity} (e.g. custom
|
||||
* conversions).
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
enum UntypedOperations implements TypedOperations<Object> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static <T> TypedOperations<T> instance() {
|
||||
return (TypedOperations) INSTANCE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.EntityOperations.TypedOperations#getCollation()
|
||||
*/
|
||||
@Override
|
||||
public Optional<Collation> getCollation() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.EntityOperations.TypedOperations#getCollation(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
public Optional<Collation> getCollation(Query query) {
|
||||
|
||||
if (query == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return query.getCollation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link TypedOperations} backed by {@link MongoPersistentEntity}.
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
static class TypedEntityOperations<T> implements TypedOperations<T> {
|
||||
|
||||
private final @NonNull MongoPersistentEntity<T> entity;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.EntityOperations.TypedOperations#getCollation()
|
||||
*/
|
||||
@Override
|
||||
public Optional<Collation> getCollation() {
|
||||
return Optional.ofNullable(entity.getCollation());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.EntityOperations.TypedOperations#getCollation(org.springframework.data.mongodb.core.query.Query)
|
||||
*/
|
||||
@Override
|
||||
public Optional<Collation> getCollation(Query query) {
|
||||
|
||||
if (query.getCollation().isPresent()) {
|
||||
return query.getCollation();
|
||||
}
|
||||
|
||||
return Optional.ofNullable(entity.getCollation());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -88,10 +88,10 @@ public interface ExecutableAggregationOperation {
|
||||
|
||||
/**
|
||||
* Apply pipeline operations as specified and stream all matching elements. <br />
|
||||
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable}
|
||||
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.Cursor}
|
||||
*
|
||||
* @return a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs
|
||||
* to be closed. Never {@literal null}.
|
||||
* @return a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.Cursor} that needs to be closed.
|
||||
* Never {@literal null}.
|
||||
*/
|
||||
CloseableIterator<T> stream();
|
||||
}
|
||||
|
||||
@@ -117,8 +117,8 @@ public interface ExecutableFindOperation {
|
||||
/**
|
||||
* Stream all matching elements.
|
||||
*
|
||||
* @return a {@link Stream} that wraps the a Mongo DB {@link com.mongodb.client.FindIterable} that needs to be
|
||||
* closed. Never {@literal null}.
|
||||
* @return a {@link Stream} that wraps the a Mongo DB {@link com.mongodb.Cursor} that needs to be closed. Never
|
||||
* {@literal null}.
|
||||
*/
|
||||
Stream<T> stream();
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
@@ -37,7 +36,6 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.ReadPreference;
|
||||
import com.mongodb.client.FindIterable;
|
||||
|
||||
/**
|
||||
@@ -258,9 +256,9 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
|
||||
* @see org.springframework.data.mongodb.core.CursorPreparer#prepare(com.mongodb.clientFindIterable)
|
||||
*/
|
||||
@Override
|
||||
public FindIterable<Document> prepare(FindIterable<Document> iterable) {
|
||||
public FindIterable<Document> prepare(FindIterable<Document> cursor) {
|
||||
|
||||
FindIterable<Document> target = delegate != null ? delegate.prepare(iterable) : iterable;
|
||||
FindIterable<Document> target = delegate != null ? delegate.prepare(cursor) : cursor;
|
||||
return limit.map(target::limit).orElse(target);
|
||||
}
|
||||
|
||||
@@ -269,11 +267,6 @@ class ExecutableFindOperationSupport implements ExecutableFindOperation {
|
||||
this.limit = Optional.of(limit);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadPreference getReadPreference() {
|
||||
return delegate.getReadPreference();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,31 +33,6 @@ public class FindAndModifyOptions {
|
||||
|
||||
private @Nullable Collation collation;
|
||||
|
||||
private static final FindAndModifyOptions NONE = new FindAndModifyOptions() {
|
||||
|
||||
private static final String ERROR_MSG = "FindAndModifyOptions.none() cannot be changed. Please use FindAndModifyOptions.options() instead.";
|
||||
|
||||
@Override
|
||||
public FindAndModifyOptions returnNew(boolean returnNew) {
|
||||
throw new UnsupportedOperationException(ERROR_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FindAndModifyOptions upsert(boolean upsert) {
|
||||
throw new UnsupportedOperationException(ERROR_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FindAndModifyOptions remove(boolean remove) {
|
||||
throw new UnsupportedOperationException(ERROR_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FindAndModifyOptions collation(@Nullable Collation collation) {
|
||||
throw new UnsupportedOperationException(ERROR_MSG);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Static factory method to create a FindAndModifyOptions instance
|
||||
*
|
||||
@@ -68,18 +43,8 @@ public class FindAndModifyOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method returning an unmodifiable {@link FindAndModifyOptions} instance.
|
||||
*
|
||||
* @return unmodifiable {@link FindAndModifyOptions} instance.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static FindAndModifyOptions none() {
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link FindAndModifyOptions} based on option of given {@literal source}.
|
||||
*
|
||||
* Create new {@link FindAndModifyOptions} based on option of given {@litearl source}.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return new instance of {@link FindAndModifyOptions}.
|
||||
* @since 2.0
|
||||
@@ -117,8 +82,8 @@ public class FindAndModifyOptions {
|
||||
/**
|
||||
* Define the {@link Collation} specifying language-specific rules for string comparison.
|
||||
*
|
||||
* @param collation can be {@literal null}.
|
||||
* @return this.
|
||||
* @param collation
|
||||
* @return
|
||||
* @since 2.0
|
||||
*/
|
||||
public FindAndModifyOptions collation(@Nullable Collation collation) {
|
||||
@@ -142,7 +107,7 @@ public class FindAndModifyOptions {
|
||||
/**
|
||||
* Get the {@link Collation} specifying language-specific rules for string comparison.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @since 2.0
|
||||
*/
|
||||
public Optional<Collation> getCollation() {
|
||||
|
||||
@@ -36,21 +36,6 @@ public class FindAndReplaceOptions {
|
||||
private boolean returnNew;
|
||||
private boolean upsert;
|
||||
|
||||
private static final FindAndReplaceOptions NONE = new FindAndReplaceOptions() {
|
||||
|
||||
private static final String ERROR_MSG = "FindAndReplaceOptions.none() cannot be changed. Please use FindAndReplaceOptions.options() instead.";
|
||||
|
||||
@Override
|
||||
public FindAndReplaceOptions returnNew() {
|
||||
throw new UnsupportedOperationException(ERROR_MSG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FindAndReplaceOptions upsert() {
|
||||
throw new UnsupportedOperationException(ERROR_MSG);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Static factory method to create a {@link FindAndReplaceOptions} instance.
|
||||
* <dl>
|
||||
@@ -66,16 +51,6 @@ public class FindAndReplaceOptions {
|
||||
return new FindAndReplaceOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method returning an unmodifiable {@link FindAndReplaceOptions} instance.
|
||||
*
|
||||
* @return unmodifiable {@link FindAndReplaceOptions} instance.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static FindAndReplaceOptions none() {
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method to create a {@link FindAndReplaceOptions} instance with
|
||||
* <dl>
|
||||
@@ -116,7 +91,7 @@ public class FindAndReplaceOptions {
|
||||
/**
|
||||
* Get the bit indicating to return the replacement document.
|
||||
*
|
||||
* @return {@literal true} if set.
|
||||
* @return
|
||||
*/
|
||||
public boolean isReturnNew() {
|
||||
return returnNew;
|
||||
@@ -125,7 +100,7 @@ public class FindAndReplaceOptions {
|
||||
/**
|
||||
* Get the bit indicating if to create a new document if not exists.
|
||||
*
|
||||
* @return {@literal true} if set.
|
||||
* @return
|
||||
*/
|
||||
public boolean isUpsert() {
|
||||
return upsert;
|
||||
|
||||
@@ -15,69 +15,20 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.ReadPreference;
|
||||
import com.mongodb.reactivestreams.client.FindPublisher;
|
||||
import com.mongodb.reactivestreams.client.MongoCollection;
|
||||
|
||||
/**
|
||||
* Simple callback interface to allow customization of a {@link FindPublisher}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @author Konstantin Volivach
|
||||
*/
|
||||
public interface FindPublisherPreparer extends ReadPreferenceAware {
|
||||
|
||||
/**
|
||||
* Default {@link FindPublisherPreparer} just passing on the given {@link FindPublisher}.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
FindPublisherPreparer NO_OP_PREPARER = (findPublisher -> findPublisher);
|
||||
public interface FindPublisherPreparer {
|
||||
|
||||
/**
|
||||
* Prepare the given cursor (apply limits, skips and so on). Returns the prepared cursor.
|
||||
*
|
||||
* @param findPublisher must not be {@literal null}.
|
||||
*/
|
||||
FindPublisher<Document> prepare(FindPublisher<Document> findPublisher);
|
||||
|
||||
/**
|
||||
* Apply query specific settings to {@link MongoCollection} and initate a find operation returning a
|
||||
* {@link FindPublisher} via the given {@link Function find} function.
|
||||
*
|
||||
* @param collection must not be {@literal null}.
|
||||
* @param find must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @throws IllegalArgumentException if one of the required arguments is {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
default FindPublisher<Document> initiateFind(MongoCollection<Document> collection,
|
||||
Function<MongoCollection<Document>, FindPublisher<Document>> find) {
|
||||
|
||||
Assert.notNull(collection, "Collection must not be null!");
|
||||
Assert.notNull(find, "Find function must not be null!");
|
||||
|
||||
if (hasReadPreference()) {
|
||||
collection = collection.withReadPreference(getReadPreference());
|
||||
}
|
||||
|
||||
return prepare(find.apply(collection));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link ReadPreference} to apply or {@literal null} if none defined.
|
||||
* @since 2.2
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
default ReadPreference getReadPreference() {
|
||||
return null;
|
||||
}
|
||||
<T> FindPublisher<T> prepare(FindPublisher<T> findPublisher);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class GeoCommandStatistics {
|
||||
* Creates a new {@link GeoCommandStatistics} from the given command result extracting the statistics.
|
||||
*
|
||||
* @param commandResult must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static GeoCommandStatistics from(Document commandResult) {
|
||||
|
||||
@@ -61,7 +61,7 @@ class GeoCommandStatistics {
|
||||
* Returns the average distance reported by the command result. Mitigating a removal of the field in case the command
|
||||
* didn't return any result introduced in MongoDB 3.2 RC1.
|
||||
*
|
||||
* @return never {@literal null}, uses {@link Double#NaN} if {@literal avgDistance} does not exist.
|
||||
* @return
|
||||
* @see <a href="https://jira.mongodb.org/browse/SERVER-21024">MongoDB Jira SERVER-21024</a>
|
||||
*/
|
||||
public double getAverageDistance() {
|
||||
|
||||
@@ -92,7 +92,7 @@ public class MappedDocument {
|
||||
* mapped to the specific domain type.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
* @since 2.1.4
|
||||
*/
|
||||
class MappedUpdate implements UpdateDefinition {
|
||||
|
||||
@@ -137,14 +137,5 @@ public class MappedDocument {
|
||||
public Boolean isIsolated() {
|
||||
return delegate.isIsolated();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.query.UpdateDefinition#getArrayFilters()
|
||||
*/
|
||||
@Override
|
||||
public List<ArrayFilter> getArrayFilters() {
|
||||
return delegate.getArrayFilters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.schema.IdentifiableJsonSchemaProperty.ObjectJsonSchemaProperty;
|
||||
import org.springframework.data.mongodb.core.schema.JsonSchemaObject;
|
||||
import org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type;
|
||||
import org.springframework.data.mongodb.core.schema.JsonSchemaProperty;
|
||||
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
|
||||
import org.springframework.data.mongodb.core.schema.MongoJsonSchema.MongoJsonSchemaBuilder;
|
||||
import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link MongoJsonSchemaCreator} implementation using both {@link MongoConverter} and {@link MappingContext} to obtain
|
||||
* domain type meta information which considers {@link org.springframework.data.mongodb.core.mapping.Field field names}
|
||||
* and {@link org.springframework.data.mongodb.core.convert.MongoCustomConversions custom conversions}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 2.2
|
||||
*/
|
||||
class MappingMongoJsonSchemaCreator implements MongoJsonSchemaCreator {
|
||||
|
||||
private final MongoConverter converter;
|
||||
private final MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
|
||||
|
||||
/**
|
||||
* Create a new instance of {@link MappingMongoJsonSchemaCreator}.
|
||||
*
|
||||
* @param converter must not be {@literal null}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
MappingMongoJsonSchemaCreator(MongoConverter converter) {
|
||||
|
||||
Assert.notNull(converter, "Converter must not be null!");
|
||||
this.converter = converter;
|
||||
this.mappingContext = (MappingContext<MongoPersistentEntity<?>, MongoPersistentProperty>) converter
|
||||
.getMappingContext();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* org.springframework.data.mongodb.core.MongoJsonSchemaCreator#createSchemaFor(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public MongoJsonSchema createSchemaFor(Class<?> type) {
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(type);
|
||||
MongoJsonSchemaBuilder schemaBuilder = MongoJsonSchema.builder();
|
||||
|
||||
List<JsonSchemaProperty> schemaProperties = computePropertiesForEntity(Collections.emptyList(), entity);
|
||||
schemaBuilder.properties(schemaProperties.toArray(new JsonSchemaProperty[0]));
|
||||
|
||||
return schemaBuilder.build();
|
||||
|
||||
}
|
||||
|
||||
private List<JsonSchemaProperty> computePropertiesForEntity(List<MongoPersistentProperty> path,
|
||||
MongoPersistentEntity<?> entity) {
|
||||
|
||||
List<JsonSchemaProperty> schemaProperties = new ArrayList<>();
|
||||
|
||||
for (MongoPersistentProperty nested : entity) {
|
||||
|
||||
List<MongoPersistentProperty> currentPath = new ArrayList<>(path);
|
||||
|
||||
if (path.contains(nested)) { // cycle guard
|
||||
schemaProperties.add(createSchemaProperty(computePropertyFieldName(CollectionUtils.lastElement(currentPath)),
|
||||
Object.class, false));
|
||||
break;
|
||||
}
|
||||
|
||||
currentPath.add(nested);
|
||||
schemaProperties.add(computeSchemaForProperty(currentPath));
|
||||
}
|
||||
|
||||
return schemaProperties;
|
||||
}
|
||||
|
||||
private JsonSchemaProperty computeSchemaForProperty(List<MongoPersistentProperty> path) {
|
||||
|
||||
MongoPersistentProperty property = CollectionUtils.lastElement(path);
|
||||
|
||||
boolean required = isRequiredProperty(property);
|
||||
Class<?> rawTargetType = computeTargetType(property); // target type before conversion
|
||||
Class<?> targetType = converter.getTypeMapper().getWriteTargetTypeFor(rawTargetType); // conversion target type
|
||||
|
||||
if (property.isEntity() && ObjectUtils.nullSafeEquals(rawTargetType, targetType)) {
|
||||
return createObjectSchemaPropertyForEntity(path, property, required);
|
||||
}
|
||||
|
||||
String fieldName = computePropertyFieldName(property);
|
||||
|
||||
if (property.isCollectionLike()) {
|
||||
return createSchemaProperty(fieldName, targetType, required);
|
||||
} else if (property.isMap()) {
|
||||
return createSchemaProperty(fieldName, Type.objectType(), required);
|
||||
} else if (ClassUtils.isAssignable(Enum.class, targetType)) {
|
||||
return createEnumSchemaProperty(fieldName, targetType, required);
|
||||
}
|
||||
|
||||
return createSchemaProperty(fieldName, targetType, required);
|
||||
}
|
||||
|
||||
private JsonSchemaProperty createObjectSchemaPropertyForEntity(List<MongoPersistentProperty> path,
|
||||
MongoPersistentProperty property, boolean required) {
|
||||
|
||||
ObjectJsonSchemaProperty target = JsonSchemaProperty.object(property.getName());
|
||||
List<JsonSchemaProperty> nestedProperties = computePropertiesForEntity(path,
|
||||
mappingContext.getRequiredPersistentEntity(property));
|
||||
|
||||
return createPotentiallyRequiredSchemaProperty(
|
||||
target.properties(nestedProperties.toArray(new JsonSchemaProperty[0])), required);
|
||||
}
|
||||
|
||||
private JsonSchemaProperty createEnumSchemaProperty(String fieldName, Class<?> targetType, boolean required) {
|
||||
|
||||
List<Object> possibleValues = new ArrayList<>();
|
||||
|
||||
for (Object enumValue : EnumSet.allOf((Class) targetType)) {
|
||||
possibleValues.add(converter.convertToMongoType(enumValue));
|
||||
}
|
||||
|
||||
targetType = possibleValues.isEmpty() ? targetType : possibleValues.iterator().next().getClass();
|
||||
return createSchemaProperty(fieldName, targetType, required, possibleValues);
|
||||
}
|
||||
|
||||
JsonSchemaProperty createSchemaProperty(String fieldName, Object type, boolean required) {
|
||||
return createSchemaProperty(fieldName, type, required, Collections.emptyList());
|
||||
}
|
||||
|
||||
JsonSchemaProperty createSchemaProperty(String fieldName, Object type, boolean required,
|
||||
Collection<?> possibleValues) {
|
||||
|
||||
TypedJsonSchemaObject schemaObject = type instanceof Type ? JsonSchemaObject.of(Type.class.cast(type))
|
||||
: JsonSchemaObject.of(Class.class.cast(type));
|
||||
|
||||
if (!CollectionUtils.isEmpty(possibleValues)) {
|
||||
schemaObject = schemaObject.possibleValues(possibleValues);
|
||||
}
|
||||
|
||||
return createPotentiallyRequiredSchemaProperty(JsonSchemaProperty.named(fieldName).with(schemaObject), required);
|
||||
}
|
||||
|
||||
private String computePropertyFieldName(PersistentProperty property) {
|
||||
|
||||
return property instanceof MongoPersistentProperty ? ((MongoPersistentProperty) property).getFieldName()
|
||||
: property.getName();
|
||||
}
|
||||
|
||||
private boolean isRequiredProperty(PersistentProperty property) {
|
||||
return property.getType().isPrimitive();
|
||||
}
|
||||
|
||||
private Class<?> computeTargetType(PersistentProperty<?> property) {
|
||||
|
||||
if (!(property instanceof MongoPersistentProperty)) {
|
||||
return property.getType();
|
||||
}
|
||||
|
||||
MongoPersistentProperty mongoProperty = (MongoPersistentProperty) property;
|
||||
if (!mongoProperty.isIdProperty()) {
|
||||
return mongoProperty.getFieldType();
|
||||
}
|
||||
|
||||
if (mongoProperty.hasExplicitWriteTarget()) {
|
||||
return mongoProperty.getRequiredAnnotation(Field.class).targetType().getJavaClass();
|
||||
}
|
||||
|
||||
return mongoProperty.getFieldType() != mongoProperty.getActualType() ? Object.class : mongoProperty.getFieldType();
|
||||
}
|
||||
|
||||
static JsonSchemaProperty createPotentiallyRequiredSchemaProperty(JsonSchemaProperty property, boolean required) {
|
||||
|
||||
if (!required) {
|
||||
return property;
|
||||
}
|
||||
|
||||
return JsonSchemaProperty.required(property);
|
||||
}
|
||||
}
|
||||
@@ -34,29 +34,14 @@ import com.mongodb.client.MongoDatabase;
|
||||
@ManagedResource(description = "Mongo Admin Operations")
|
||||
public class MongoAdmin implements MongoAdminOperations {
|
||||
|
||||
private final Object mongoClient;
|
||||
private final MongoClient mongoClient;
|
||||
|
||||
/**
|
||||
* @param mongoClient
|
||||
* @deprecated since 2.2 in favor of {@link MongoAdmin#MongoAdmin(com.mongodb.client.MongoClient)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public MongoAdmin(MongoClient mongoClient) {
|
||||
|
||||
Assert.notNull(mongoClient, "MongoClient must not be null!");
|
||||
this.mongoClient = mongoClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param client the underlying {@link com.mongodb.client.MongoClient} used for data access.
|
||||
* @since 2.2
|
||||
*/
|
||||
public MongoAdmin(com.mongodb.client.MongoClient client) {
|
||||
|
||||
Assert.notNull(client, "Client must not be null!");
|
||||
this.mongoClient = client;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.core.MongoAdminOperations#dropDatabase(java.lang.String)
|
||||
*/
|
||||
@@ -88,11 +73,6 @@ public class MongoAdmin implements MongoAdminOperations {
|
||||
}
|
||||
|
||||
MongoDatabase getDB(String databaseName) {
|
||||
|
||||
if (mongoClient instanceof MongoClient) {
|
||||
return ((MongoClient) mongoClient).getDatabase(databaseName);
|
||||
}
|
||||
|
||||
return ((com.mongodb.client.MongoClient) mongoClient).getDatabase(databaseName);
|
||||
return mongoClient.getDatabase(databaseName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,7 @@ import com.mongodb.ServerAddress;
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 1.7
|
||||
* @deprecated since 2.2 - There is no replacement for this {@link org.springframework.beans.factory.FactoryBean} at
|
||||
* this time. However moving forward the {@link org.springframework.beans.factory.FactoryBean} will be
|
||||
* suitable to provide instances of {@link com.mongodb.client.MongoClient}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class MongoClientFactoryBean extends AbstractFactoryBean<MongoClient> implements PersistenceExceptionTranslator {
|
||||
|
||||
private static final PersistenceExceptionTranslator DEFAULT_EXCEPTION_TRANSLATOR = new MongoExceptionTranslator();
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import com.mongodb.AutoEncryptionSettings;
|
||||
import com.mongodb.DBDecoderFactory;
|
||||
import com.mongodb.DBEncoderFactory;
|
||||
import com.mongodb.MongoClient;
|
||||
@@ -37,17 +36,12 @@ import com.mongodb.WriteConcern;
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 1.7
|
||||
* @deprecated since 2.2 - There is no replacement for this {@link org.springframework.beans.factory.FactoryBean}.
|
||||
* However moving forward there will be a dedicated factory bean for {@link com.mongodb.MongoClientSettings}
|
||||
* replacing {@link MongoClientOptions}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClientOptions> {
|
||||
|
||||
private static final MongoClientOptions DEFAULT_MONGO_OPTIONS = MongoClientOptions.builder().build();
|
||||
|
||||
// TODO: Mongo Driver 4 - use application name insetad of description if not available
|
||||
private @Nullable String description = DEFAULT_MONGO_OPTIONS.getApplicationName();
|
||||
private @Nullable String description = DEFAULT_MONGO_OPTIONS.getDescription();
|
||||
private int minConnectionsPerHost = DEFAULT_MONGO_OPTIONS.getMinConnectionsPerHost();
|
||||
private int connectionsPerHost = DEFAULT_MONGO_OPTIONS.getConnectionsPerHost();
|
||||
private int threadsAllowedToBlockForConnectionMultiplier = DEFAULT_MONGO_OPTIONS
|
||||
@@ -57,8 +51,6 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
|
||||
private int maxConnectionLifeTime = DEFAULT_MONGO_OPTIONS.getMaxConnectionLifeTime();
|
||||
private int connectTimeout = DEFAULT_MONGO_OPTIONS.getConnectTimeout();
|
||||
private int socketTimeout = DEFAULT_MONGO_OPTIONS.getSocketTimeout();
|
||||
|
||||
// TODO: Mongo Driver 4 - check if available
|
||||
private boolean socketKeepAlive = DEFAULT_MONGO_OPTIONS.isSocketKeepAlive();
|
||||
private @Nullable ReadPreference readPreference = DEFAULT_MONGO_OPTIONS.getReadPreference();
|
||||
private DBDecoderFactory dbDecoderFactory = DEFAULT_MONGO_OPTIONS.getDbDecoderFactory();
|
||||
@@ -66,8 +58,6 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
|
||||
private @Nullable WriteConcern writeConcern = DEFAULT_MONGO_OPTIONS.getWriteConcern();
|
||||
private @Nullable SocketFactory socketFactory = DEFAULT_MONGO_OPTIONS.getSocketFactory();
|
||||
private boolean cursorFinalizerEnabled = DEFAULT_MONGO_OPTIONS.isCursorFinalizerEnabled();
|
||||
|
||||
// TODO: Mongo Driver 4 - remove this option
|
||||
private boolean alwaysUseMBeans = DEFAULT_MONGO_OPTIONS.isAlwaysUseMBeans();
|
||||
private int heartbeatFrequency = DEFAULT_MONGO_OPTIONS.getHeartbeatFrequency();
|
||||
private int minHeartbeatFrequency = DEFAULT_MONGO_OPTIONS.getMinHeartbeatFrequency();
|
||||
@@ -78,14 +68,12 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
|
||||
|
||||
private boolean ssl;
|
||||
private @Nullable SSLSocketFactory sslSocketFactory;
|
||||
private @Nullable AutoEncryptionSettings autoEncryptionSettings;
|
||||
|
||||
/**
|
||||
* Set the {@link MongoClient} description.
|
||||
*
|
||||
* @param description
|
||||
*/
|
||||
// TODO: Mongo Driver 4 - deprecate that one and add application name
|
||||
public void setDescription(@Nullable String description) {
|
||||
this.description = description;
|
||||
}
|
||||
@@ -247,7 +235,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
|
||||
}
|
||||
|
||||
/**
|
||||
* This controls if the driver should us an SSL connection. Defaults to {@literal false}.
|
||||
* This controls if the driver should us an SSL connection. Defaults to |@literal false}.
|
||||
*
|
||||
* @param ssl
|
||||
*/
|
||||
@@ -278,16 +266,6 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
|
||||
this.serverSelectionTimeout = serverSelectionTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link AutoEncryptionSettings} to be used.
|
||||
*
|
||||
* @param autoEncryptionSettings can be {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public void setAutoEncryptionSettings(@Nullable AutoEncryptionSettings autoEncryptionSettings) {
|
||||
this.autoEncryptionSettings = autoEncryptionSettings;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
|
||||
@@ -307,7 +285,7 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
|
||||
.cursorFinalizerEnabled(cursorFinalizerEnabled) //
|
||||
.dbDecoderFactory(dbDecoderFactory) //
|
||||
.dbEncoderFactory(dbEncoderFactory) //
|
||||
.applicationName(description) // TODO: Mongo Driver 4 - use application name if description not available
|
||||
.description(description) //
|
||||
.heartbeatConnectTimeout(heartbeatConnectTimeout) //
|
||||
.heartbeatFrequency(heartbeatFrequency) //
|
||||
.heartbeatSocketTimeout(heartbeatSocketTimeout) //
|
||||
@@ -319,10 +297,8 @@ public class MongoClientOptionsFactoryBean extends AbstractFactoryBean<MongoClie
|
||||
.readPreference(readPreference) //
|
||||
.requiredReplicaSetName(requiredReplicaSetName) //
|
||||
.serverSelectionTimeout(serverSelectionTimeout) //
|
||||
.sslEnabled(ssl) //
|
||||
.autoEncryptionSettings(autoEncryptionSettings) //
|
||||
.socketFactory(socketFactoryToUse) // TODO: Mongo Driver 4 -
|
||||
.socketKeepAlive(socketKeepAlive) // TODO: Mongo Driver 4 - remove if not available
|
||||
.socketFactory(socketFactoryToUse) //
|
||||
.socketKeepAlive(socketKeepAlive) //
|
||||
.socketTimeout(socketTimeout) //
|
||||
.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier) //
|
||||
.writeConcern(writeConcern).build();
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bson.BsonDocument;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import com.mongodb.AutoEncryptionSettings;
|
||||
import com.mongodb.MongoClientSettings;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} for creating {@link AutoEncryptionSettings} using the {@link AutoEncryptionSettings.Builder}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
*/
|
||||
public class MongoEncryptionSettingsFactoryBean implements FactoryBean<AutoEncryptionSettings> {
|
||||
|
||||
private boolean bypassAutoEncryption;
|
||||
private String keyVaultNamespace;
|
||||
private Map<String, Object> extraOptions;
|
||||
private MongoClientSettings keyVaultClientSettings;
|
||||
private Map<String, Map<String, Object>> kmsProviders;
|
||||
private Map<String, BsonDocument> schemaMap;
|
||||
|
||||
/**
|
||||
* @param bypassAutoEncryption
|
||||
* @see AutoEncryptionSettings.Builder#bypassAutoEncryption(boolean)
|
||||
*/
|
||||
public void setBypassAutoEncryption(boolean bypassAutoEncryption) {
|
||||
this.bypassAutoEncryption = bypassAutoEncryption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extraOptions
|
||||
* @see AutoEncryptionSettings.Builder#extraOptions(Map)
|
||||
*/
|
||||
public void setExtraOptions(Map<String, Object> extraOptions) {
|
||||
this.extraOptions = extraOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keyVaultNamespace
|
||||
* @see AutoEncryptionSettings.Builder#keyVaultNamespace(String)
|
||||
*/
|
||||
public void setKeyVaultNamespace(String keyVaultNamespace) {
|
||||
this.keyVaultNamespace = keyVaultNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param keyVaultClientSettings
|
||||
* @see AutoEncryptionSettings.Builder#keyVaultMongoClientSettings(MongoClientSettings)
|
||||
*/
|
||||
public void setKeyVaultClientSettings(MongoClientSettings keyVaultClientSettings) {
|
||||
this.keyVaultClientSettings = keyVaultClientSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param kmsProviders
|
||||
* @see AutoEncryptionSettings.Builder#kmsProviders(Map)
|
||||
*/
|
||||
public void setKmsProviders(Map<String, Map<String, Object>> kmsProviders) {
|
||||
this.kmsProviders = kmsProviders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param schemaMap
|
||||
* @see AutoEncryptionSettings.Builder#schemaMap(Map)
|
||||
*/
|
||||
public void setSchemaMap(Map<String, BsonDocument> schemaMap) {
|
||||
this.schemaMap = schemaMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
*/
|
||||
@Override
|
||||
public AutoEncryptionSettings getObject() {
|
||||
|
||||
return AutoEncryptionSettings.builder() //
|
||||
.bypassAutoEncryption(bypassAutoEncryption) //
|
||||
.keyVaultNamespace(keyVaultNamespace) //
|
||||
.keyVaultMongoClientSettings(keyVaultClientSettings) //
|
||||
.kmsProviders(orEmpty(kmsProviders)) //
|
||||
.extraOptions(orEmpty(extraOptions)) //
|
||||
.schemaMap(orEmpty(schemaMap)) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private <K, V> Map<K, V> orEmpty(@Nullable Map<K, V> source) {
|
||||
return source != null ? source : Collections.emptyMap();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return AutoEncryptionSettings.class;
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link MongoJsonSchemaCreator} extracts the {@link MongoJsonSchema} for a given {@link Class} by applying the
|
||||
* following mapping rules.
|
||||
* <p>
|
||||
* <strong>Required Properties</strong>
|
||||
* <ul>
|
||||
* <li>Properties of primitive type</li>
|
||||
* </ul>
|
||||
* <strong>Ignored Properties</strong>
|
||||
* <ul>
|
||||
* <li>All properties annotated with {@link org.springframework.data.annotation.Transient}</li>
|
||||
* </ul>
|
||||
* <strong>Property Type Mapping</strong>
|
||||
* <ul>
|
||||
* <li>{@link java.lang.Object} -> {@code type : 'object'}</li>
|
||||
* <li>{@link java.util.Arrays} -> {@code type : 'array'}</li>
|
||||
* <li>{@link java.util.Collection} -> {@code type : 'array'}</li>
|
||||
* <li>{@link java.util.Map} -> {@code type : 'object'}</li>
|
||||
* <li>{@link java.lang.Enum} -> {@code type : 'string', enum : [the enum values]}</li>
|
||||
* <li>Simple Types -> {@code type : 'the corresponding bson type' }</li>
|
||||
* <li>Domain Types -> {@code type : 'object', properties : {the types properties} }</li>
|
||||
* </ul>
|
||||
* <br />
|
||||
* {@link org.springframework.data.annotation.Id _id} properties using types that can be converted into
|
||||
* {@link org.bson.types.ObjectId} like {@link String} will be mapped to {@code type : 'object'} unless there is more
|
||||
* specific information available via the {@link org.springframework.data.mongodb.core.mapping.MongoId} annotation.
|
||||
* </p>
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface MongoJsonSchemaCreator {
|
||||
|
||||
/**
|
||||
* Create the {@link MongoJsonSchema} for the given {@link Class type}.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
MongoJsonSchema createSchemaFor(Class<?> type);
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoJsonSchemaCreator} that is aware of conversions applied by the given
|
||||
* {@link MongoConverter}.
|
||||
*
|
||||
* @param mongoConverter must not be {@literal null}.
|
||||
* @return new instance of {@link MongoJsonSchemaCreator}.
|
||||
*/
|
||||
static MongoJsonSchemaCreator create(MongoConverter mongoConverter) {
|
||||
|
||||
Assert.notNull(mongoConverter, "MongoConverter must not be null!");
|
||||
return new MappingMongoJsonSchemaCreator(mongoConverter);
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
* The collection name used for the specified class by this template.
|
||||
*
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
String getCollectionName(Class<?> entityClass);
|
||||
|
||||
@@ -360,11 +360,9 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
/**
|
||||
* Returns the {@link ScriptOperations} that can be performed on {@link com.mongodb.DB} level.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @since 1.7
|
||||
* @deprecated since 2.2. The {@code eval} command has been removed without replacement in MongoDB Server 4.2.0.
|
||||
*/
|
||||
@Deprecated
|
||||
ScriptOperations scriptOps();
|
||||
|
||||
/**
|
||||
@@ -436,11 +434,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
* reduce function.
|
||||
* @param entityClass The parametrized type of the returned list
|
||||
* @return The results of the group operation
|
||||
* @deprecated since 2.2. The {@code group} command has been removed in MongoDB Server 4.2.0. <br />
|
||||
* Please use {@link #aggregate(TypedAggregation, String, Class) } with a
|
||||
* {@link org.springframework.data.mongodb.core.aggregation.GroupOperation} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
<T> GroupByResults<T> group(String inputCollectionName, GroupBy groupBy, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
@@ -455,12 +449,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
* reduce function.
|
||||
* @param entityClass The parametrized type of the returned list
|
||||
* @return The results of the group operation
|
||||
* @deprecated since 2.2. The {@code group} command has been removed in MongoDB Server 4.2.0. <br />
|
||||
* Please use {@link #aggregate(TypedAggregation, String, Class) } with a
|
||||
* {@link org.springframework.data.mongodb.core.aggregation.GroupOperation} and
|
||||
* {@link org.springframework.data.mongodb.core.aggregation.MatchOperation} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
<T> GroupByResults<T> group(@Nullable Criteria criteria, String inputCollectionName, GroupBy groupBy,
|
||||
Class<T> entityClass);
|
||||
|
||||
@@ -648,52 +637,24 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
* information to determine the collection the query is ran against. Note, that MongoDB limits the number of results
|
||||
* by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect a particular number of
|
||||
* results.
|
||||
* <p>
|
||||
* MongoDB 4.2 has removed the {@code geoNear} command. This method uses since version 2.2 aggregations and the
|
||||
* {@code $geoNear} aggregation command to emulate {@code geoNear} command functionality. We recommend using
|
||||
* aggregations directly:
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* TypedAggregation<T> geoNear = TypedAggregation.newAggregation(entityClass, Aggregation.geoNear(near, "dis"))
|
||||
* .withOptions(AggregationOptions.builder().collation(near.getCollation()).build());
|
||||
* AggregationResults<Document> results = aggregate(geoNear, Document.class);
|
||||
* </pre>
|
||||
*
|
||||
* @param near must not be {@literal null}.
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return
|
||||
* @deprecated since 2.2. The {@code eval} command has been removed in MongoDB Server 4.2.0. Use Aggregations with
|
||||
* {@link Aggregation#geoNear(NearQuery, String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
<T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Returns {@link GeoResults} for all entities matching the given {@link NearQuery}. Note, that MongoDB limits the
|
||||
* number of results by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect a
|
||||
* particular number of results.
|
||||
* <p>
|
||||
* MongoDB 4.2 has removed the {@code geoNear} command. This method uses since version 2.2 aggregations and the
|
||||
* {@code $geoNear} aggregation command to emulate {@code geoNear} command functionality. We recommend using
|
||||
* aggregations directly:
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* TypedAggregation<T> geoNear = TypedAggregation.newAggregation(entityClass, Aggregation.geoNear(near, "dis"))
|
||||
* .withOptions(AggregationOptions.builder().collation(near.getCollation()).build());
|
||||
* AggregationResults<Document> results = aggregate(geoNear, Document.class);
|
||||
* </pre>
|
||||
*
|
||||
* @param near must not be {@literal null}.
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @param collectionName the collection to trigger the query against. If no collection name is given the entity class
|
||||
* will be inspected. Must not be {@literal null} nor empty.
|
||||
* @return
|
||||
* @deprecated since 2.2. The {@code eval} command has been removed in MongoDB Server 4.2.0. Use Aggregations with
|
||||
* {@link Aggregation#geoNear(NearQuery, String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
<T> GeoResults<T> geoNear(NearQuery near, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
@@ -1140,11 +1101,6 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
|
||||
* <br />
|
||||
* <strong>NOTE:</strong> Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
|
||||
* influence on the resulting number of documents found as those values are passed on to the server and potentially
|
||||
* limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to
|
||||
* count all matches.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
|
||||
* {@literal null}.
|
||||
@@ -1156,11 +1112,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
|
||||
* must solely consist of document field references as we lack type information to map potential property references
|
||||
* onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support. <br />
|
||||
* <strong>NOTE:</strong> Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
|
||||
* influence on the resulting number of documents found as those values are passed on to the server and potentially
|
||||
* limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to
|
||||
* count all matches.
|
||||
* onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the criteria used to find documents.
|
||||
* @param collectionName must not be {@literal null} or empty.
|
||||
@@ -1171,11 +1123,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
|
||||
* class to map the given {@link Query}. <br />
|
||||
* <strong>NOTE:</strong> Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
|
||||
* influence on the resulting number of documents found as those values are passed on to the server and potentially
|
||||
* limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to
|
||||
* count all matches.
|
||||
* class to map the given {@link Query}.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
|
||||
* {@literal null}.
|
||||
@@ -1193,8 +1141,8 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's
|
||||
* Type Conversion"</a> for more details.
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's Type
|
||||
* Conversion"</a> for more details.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Insert is used to initially store the object into the database. To update an existing object use the save method.
|
||||
@@ -1255,8 +1203,8 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's
|
||||
* Type Conversion"</a> for more details.
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's Type
|
||||
* Conversion"</a> for more details.
|
||||
*
|
||||
* @param objectToSave the object to store in the collection. Must not be {@literal null}.
|
||||
* @return the saved object.
|
||||
@@ -1423,10 +1371,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
UpdateResult updateMulti(Query query, Update update, Class<?> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
* Remove the given object from the collection by {@literal id} and (if applicable) its
|
||||
* {@link org.springframework.data.annotation.Version}. <br />
|
||||
* Use {@link DeleteResult#getDeletedCount()} for insight whether an {@link DeleteResult#wasAcknowledged()
|
||||
* acknowledged} remove operation was successful or not.
|
||||
* Remove the given object from the collection by id.
|
||||
*
|
||||
* @param object must not be {@literal null}.
|
||||
* @return the {@link DeleteResult} which lets you access the results of the previous delete.
|
||||
@@ -1434,10 +1379,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
DeleteResult remove(Object object);
|
||||
|
||||
/**
|
||||
* Removes the given object from the given collection by {@literal id} and (if applicable) its
|
||||
* {@link org.springframework.data.annotation.Version}. <br />
|
||||
* Use {@link DeleteResult#getDeletedCount()} for insight whether an {@link DeleteResult#wasAcknowledged()
|
||||
* acknowledged} remove operation was successful or not.
|
||||
* Removes the given object from the given collection.
|
||||
*
|
||||
* @param object must not be {@literal null}.
|
||||
* @param collectionName name of the collection where the objects will removed, must not be {@literal null} or empty.
|
||||
@@ -1520,7 +1462,7 @@ public interface MongoOperations extends FluentMongoOperations {
|
||||
/**
|
||||
* Returns the underlying {@link MongoConverter}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
MongoConverter getConverter();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bson.BsonTimestamp;
|
||||
import org.bson.BsonValue;
|
||||
import org.springframework.data.mongodb.core.ChangeStreamOptions.ChangeStreamOptionsBuilder;
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
|
||||
/**
|
||||
* {@link ReactiveChangeStreamOperation} allows creation and execution of reactive MongoDB
|
||||
* <a href="https://docs.mongodb.com/manual/changeStreams/">Change Stream</a> operations in a fluent API style. <br />
|
||||
* The starting {@literal domainType} is used for mapping a potentially given
|
||||
* {@link org.springframework.data.mongodb.core.aggregation.TypedAggregation} used for filtering. By default, the
|
||||
* originating {@literal domainType} is also used for mapping back the result from the {@link org.bson.Document}.
|
||||
* However, it is possible to define an different {@literal returnType} via {@code as}.<br />
|
||||
* The collection to operate on is optional in which case call collection with the actual database are watched, use
|
||||
* {@literal watchCollection} to define a fixed collection.
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* changeStream(Jedi.class)
|
||||
* .watchCollection("star-wars")
|
||||
* .filter(where("operationType").is("insert"))
|
||||
* .resumeAt(Instant.now())
|
||||
* .listen();
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface ReactiveChangeStreamOperation {
|
||||
|
||||
/**
|
||||
* Start creating a change stream operation for the given {@literal domainType} watching all collections within the
|
||||
* database. <br />
|
||||
* Consider limiting events be defining a {@link ChangeStreamWithCollection#watchCollection(String) collection} and/or
|
||||
* {@link ChangeStreamWithFilterAndProjection#filter(CriteriaDefinition) filter}.
|
||||
*
|
||||
* @param domainType must not be {@literal null}. Use {@link org.bson.Document} to obtain raw elements.
|
||||
* @return new instance of {@link ReactiveChangeStream}. Never {@literal null}.
|
||||
* @throws IllegalArgumentException if domainType is {@literal null}.
|
||||
*/
|
||||
<T> ReactiveChangeStream<T> changeStream(Class<T> domainType);
|
||||
|
||||
/**
|
||||
* Compose change stream execution by calling one of the terminating methods.
|
||||
*/
|
||||
interface TerminatingChangeStream<T> {
|
||||
|
||||
/**
|
||||
* Start listening to changes. The stream will not be completed unless the {@link org.reactivestreams.Subscription}
|
||||
* is {@link org.reactivestreams.Subscription#cancel() canceled}.
|
||||
* <p />
|
||||
* However, the stream may become dead, or invalid, if all watched collections, databases are dropped.
|
||||
*/
|
||||
Flux<ChangeStreamEvent<T>> listen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collection override (optional).
|
||||
*/
|
||||
interface ChangeStreamWithCollection<T> {
|
||||
|
||||
/**
|
||||
* Explicitly set the name of the collection to watch.<br />
|
||||
* Skip this step to watch all collections within the database.
|
||||
*
|
||||
* @param collection must not be {@literal null} nor {@literal empty}.
|
||||
* @return new instance of {@link ChangeStreamWithFilterAndProjection}.
|
||||
* @throws IllegalArgumentException if {@code collection} is {@literal null}.
|
||||
*/
|
||||
ChangeStreamWithFilterAndProjection<T> watchCollection(String collection);
|
||||
|
||||
/**
|
||||
* Set the the collection to watch. Collection name is derived from the {@link Class entityClass}.<br />
|
||||
* Skip this step to watch all collections within the database.
|
||||
*
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return new instance of {@link ChangeStreamWithFilterAndProjection}.
|
||||
* @throws IllegalArgumentException if {@code entityClass} is {@literal null}.
|
||||
*/
|
||||
ChangeStreamWithFilterAndProjection<T> watchCollection(Class<?> entityClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a filter for limiting results (optional).
|
||||
*/
|
||||
interface ChangeStreamWithFilterAndProjection<T> extends ResumingChangeStream<T>, TerminatingChangeStream<T> {
|
||||
|
||||
/**
|
||||
* Use an {@link Aggregation} to filter matching events.
|
||||
*
|
||||
* @param by must not be {@literal null}.
|
||||
* @return new instance of {@link ChangeStreamWithFilterAndProjection}.
|
||||
* @throws IllegalArgumentException if the given {@link Aggregation} is {@literal null}.
|
||||
*/
|
||||
ChangeStreamWithFilterAndProjection<T> filter(Aggregation by);
|
||||
|
||||
/**
|
||||
* Use a {@link CriteriaDefinition critera} to filter matching events via an
|
||||
* {@link org.springframework.data.mongodb.core.aggregation.MatchOperation}.
|
||||
*
|
||||
* @param by must not be {@literal null}.
|
||||
* @return new instance of {@link ChangeStreamWithFilterAndProjection}.
|
||||
* @throws IllegalArgumentException if the given {@link CriteriaDefinition} is {@literal null}.
|
||||
*/
|
||||
ChangeStreamWithFilterAndProjection<T> filter(CriteriaDefinition by);
|
||||
|
||||
/**
|
||||
* Define the target type fields should be mapped to.
|
||||
*
|
||||
* @param resultType must not be {@literal null}.
|
||||
* @param <R> result type.
|
||||
* @return new instance of {@link ChangeStreamWithFilterAndProjection}.
|
||||
* @throws IllegalArgumentException if resultType is {@literal null}.
|
||||
*/
|
||||
<R> ChangeStreamWithFilterAndProjection<R> as(Class<R> resultType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume a change stream. (optional).
|
||||
*/
|
||||
interface ResumingChangeStream<T> extends TerminatingChangeStream<T> {
|
||||
|
||||
/**
|
||||
* Resume the change stream at a given point.
|
||||
*
|
||||
* @param token an {@link Instant} or {@link BsonTimestamp}
|
||||
* @return new instance of {@link TerminatingChangeStream}.
|
||||
* @see ChangeStreamOptionsBuilder#resumeAt(Instant)
|
||||
* @see ChangeStreamOptionsBuilder#resumeAt(BsonTimestamp)
|
||||
* @throws IllegalArgumentException if the given beacon is neither {@link Instant} nor {@link BsonTimestamp}.
|
||||
*/
|
||||
TerminatingChangeStream<T> resumeAt(Object token);
|
||||
|
||||
/**
|
||||
* Resume the change stream after a given point.
|
||||
*
|
||||
* @param token an {@link Instant} or {@link BsonTimestamp}
|
||||
* @return new instance of {@link TerminatingChangeStream}.
|
||||
* @see ChangeStreamOptionsBuilder#resumeAfter(BsonValue)
|
||||
* @see ChangeStreamOptionsBuilder#resumeToken(BsonValue)
|
||||
* @throws IllegalArgumentException if the given beacon not a {@link BsonValue}.
|
||||
*/
|
||||
TerminatingChangeStream<T> resumeAfter(Object token);
|
||||
|
||||
/**
|
||||
* Start the change stream after a given point.
|
||||
*
|
||||
* @param token an {@link Instant} or {@link BsonTimestamp}
|
||||
* @return new instance of {@link TerminatingChangeStream}.
|
||||
* @see ChangeStreamOptionsBuilder#startAfter(BsonValue) (BsonValue)
|
||||
* @throws IllegalArgumentException if the given beacon not a {@link BsonValue}.
|
||||
*/
|
||||
TerminatingChangeStream<T> startAfter(Object token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide some options.
|
||||
*/
|
||||
interface ChangeStreamWithOptions<T> {
|
||||
|
||||
/**
|
||||
* Provide some options via the callback by modifying the given {@link ChangeStreamOptionsBuilder}. Previously
|
||||
* defined options like a {@link ResumingChangeStream#resumeAfter(Object) resumeToken} are carried over to the
|
||||
* builder and can be overwritten via eg. {@link ChangeStreamOptionsBuilder#resumeToken(BsonValue)}.
|
||||
*
|
||||
* @param optionsConsumer never {@literal null}.
|
||||
* @return new instance of {@link ReactiveChangeStream}.
|
||||
*/
|
||||
ReactiveChangeStream<T> withOptions(Consumer<ChangeStreamOptionsBuilder> optionsConsumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ReactiveChangeStream} provides methods for constructing change stream operations in a fluent way.
|
||||
*/
|
||||
interface ReactiveChangeStream<T> extends ChangeStreamWithOptions<T>, ChangeStreamWithCollection<T>,
|
||||
TerminatingChangeStream<T>, ResumingChangeStream<T>, ChangeStreamWithFilterAndProjection<T> {}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bson.BsonTimestamp;
|
||||
import org.bson.BsonValue;
|
||||
import org.bson.Document;
|
||||
import org.springframework.data.mongodb.core.ChangeStreamOptions.ChangeStreamOptionsBuilder;
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
|
||||
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2.2
|
||||
*/
|
||||
class ReactiveChangeStreamOperationSupport implements ReactiveChangeStreamOperation {
|
||||
|
||||
private final ReactiveMongoTemplate template;
|
||||
|
||||
/**
|
||||
* @param template must not be {@literal null}.
|
||||
*/
|
||||
ReactiveChangeStreamOperationSupport(ReactiveMongoTemplate template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation#changeStream(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> ReactiveChangeStream<T> changeStream(Class<T> domainType) {
|
||||
|
||||
Assert.notNull(domainType, "DomainType must not be null!");
|
||||
return new ReactiveChangeStreamSupport<>(template, domainType, domainType, null, null);
|
||||
}
|
||||
|
||||
static class ReactiveChangeStreamSupport<T>
|
||||
implements ReactiveChangeStream<T>, ChangeStreamWithFilterAndProjection<T> {
|
||||
|
||||
private final ReactiveMongoTemplate template;
|
||||
private final Class<?> domainType;
|
||||
private final Class<T> returnType;
|
||||
private final @Nullable String collection;
|
||||
private final @Nullable ChangeStreamOptions options;
|
||||
|
||||
private ReactiveChangeStreamSupport(ReactiveMongoTemplate template, Class<?> domainType, Class<T> returnType,
|
||||
@Nullable String collection, @Nullable ChangeStreamOptions options) {
|
||||
|
||||
this.template = template;
|
||||
this.domainType = domainType;
|
||||
this.returnType = returnType;
|
||||
this.collection = collection;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ChangeStreamWithCollection#watchCollection(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public ChangeStreamWithFilterAndProjection<T> watchCollection(String collection) {
|
||||
|
||||
Assert.hasText(collection, "Collection name must not be null nor empty!");
|
||||
|
||||
return new ReactiveChangeStreamSupport<>(template, domainType, returnType, collection, options);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ChangeStreamWithCollection#watchCollection(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public ChangeStreamWithFilterAndProjection<T> watchCollection(Class<?> entityClass) {
|
||||
|
||||
Assert.notNull(entityClass, "Collection type not be null!");
|
||||
|
||||
return watchCollection(template.getCollectionName(entityClass));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ResumingChangeStream#resumeAt(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public TerminatingChangeStream<T> resumeAt(Object token) {
|
||||
|
||||
return withOptions(builder -> {
|
||||
|
||||
if (token instanceof Instant) {
|
||||
builder.resumeAt((Instant) token);
|
||||
} else if (token instanceof BsonTimestamp) {
|
||||
builder.resumeAt((BsonTimestamp) token);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ResumingChangeStream#resumeAfter(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public TerminatingChangeStream<T> resumeAfter(Object token) {
|
||||
|
||||
Assert.isInstanceOf(BsonValue.class, token, "Token must be a BsonValue");
|
||||
|
||||
return withOptions(builder -> builder.resumeAfter((BsonValue) token));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ResumingChangeStream#startAfter(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public TerminatingChangeStream<T> startAfter(Object token) {
|
||||
|
||||
Assert.isInstanceOf(BsonValue.class, token, "Token must be a BsonValue");
|
||||
|
||||
return withOptions(builder -> builder.startAfter((BsonValue) token));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ChangeStreamWithOptions#withOptions(java.util.function.Consumer)
|
||||
*/
|
||||
@Override
|
||||
public ReactiveChangeStreamSupport<T> withOptions(Consumer<ChangeStreamOptionsBuilder> optionsConsumer) {
|
||||
|
||||
ChangeStreamOptionsBuilder builder = initOptionsBuilder();
|
||||
optionsConsumer.accept(builder);
|
||||
|
||||
return new ReactiveChangeStreamSupport<>(template, domainType, returnType, collection, builder.build());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ChangeStreamWithProjection#as(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <R> ChangeStreamWithFilterAndProjection<R> as(Class<R> resultType) {
|
||||
|
||||
Assert.notNull(resultType, "ResultType must not be null!");
|
||||
|
||||
return new ReactiveChangeStreamSupport<>(template, domainType, resultType, collection, options);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ChangeStreamWithFilter#filter(org.springframework.data.mongodb.core.aggregation.Aggregation)
|
||||
*/
|
||||
@Override
|
||||
public ChangeStreamWithFilterAndProjection<T> filter(Aggregation filter) {
|
||||
return withOptions(builder -> builder.filter(filter));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.ChangeStreamWithFilter#filter(org.springframework.data.mongodb.core.query.CriteriaDefinition)
|
||||
*/
|
||||
@Override
|
||||
public ChangeStreamWithFilterAndProjection<T> filter(CriteriaDefinition by) {
|
||||
|
||||
MatchOperation $match = Aggregation.match(by);
|
||||
Aggregation aggregation = !Document.class.equals(domainType) ? Aggregation.newAggregation(domainType, $match)
|
||||
: Aggregation.newAggregation($match);
|
||||
return filter(aggregation);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.ReactiveChangeStreamOperation.TerminatingChangeStream#listen()
|
||||
*/
|
||||
@Override
|
||||
public Flux<ChangeStreamEvent<T>> listen() {
|
||||
return template.changeStream(collection, options != null ? options : ChangeStreamOptions.empty(), returnType);
|
||||
}
|
||||
|
||||
private ChangeStreamOptionsBuilder initOptionsBuilder() {
|
||||
|
||||
ChangeStreamOptionsBuilder builder = ChangeStreamOptions.builder();
|
||||
if (options == null) {
|
||||
return builder;
|
||||
}
|
||||
|
||||
options.getFilter().ifPresent(it -> {
|
||||
if (it instanceof Aggregation) {
|
||||
builder.filter((Aggregation) it);
|
||||
} else {
|
||||
builder.filter(((List<Document>) it).toArray(new Document[0]));
|
||||
}
|
||||
});
|
||||
options.getFullDocumentLookup().ifPresent(builder::fullDocumentLookup);
|
||||
options.getCollation().ifPresent(builder::collation);
|
||||
|
||||
if (options.isResumeAfter()) {
|
||||
options.getResumeToken().ifPresent(builder::resumeAfter);
|
||||
options.getResumeBsonTimestamp().ifPresent(builder::resumeAfter);
|
||||
} else if (options.isStartAfter()) {
|
||||
options.getResumeToken().ifPresent(builder::startAfter);
|
||||
} else {
|
||||
options.getResumeTimestamp().ifPresent(builder::resumeAt);
|
||||
options.getResumeBsonTimestamp().ifPresent(builder::resumeAt);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
@@ -32,6 +31,8 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.reactivestreams.client.FindPublisher;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ReactiveFindOperation}.
|
||||
*
|
||||
@@ -119,7 +120,12 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
|
||||
public Mono<T> first() {
|
||||
|
||||
FindPublisherPreparer preparer = getCursorPreparer(query);
|
||||
Flux<T> result = doFind(publisher -> preparer.prepare(publisher).limit(1));
|
||||
Flux<T> result = doFind(new FindPublisherPreparer() {
|
||||
@Override
|
||||
public <D> FindPublisher<D> prepare(FindPublisher<D> publisher) {
|
||||
return preparer.prepare(publisher).limit(1);
|
||||
}
|
||||
});
|
||||
|
||||
return result.next();
|
||||
}
|
||||
@@ -132,7 +138,12 @@ class ReactiveFindOperationSupport implements ReactiveFindOperation {
|
||||
public Mono<T> one() {
|
||||
|
||||
FindPublisherPreparer preparer = getCursorPreparer(query);
|
||||
Flux<T> result = doFind(publisher -> preparer.prepare(publisher).limit(2));
|
||||
Flux<T> result = doFind(new FindPublisherPreparer() {
|
||||
@Override
|
||||
public <D> FindPublisher<D> prepare(FindPublisher<D> publisher) {
|
||||
return preparer.prepare(publisher).limit(2);
|
||||
}
|
||||
});
|
||||
|
||||
return result.collectList().flatMap(it -> {
|
||||
|
||||
|
||||
@@ -23,4 +23,4 @@ package org.springframework.data.mongodb.core;
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface ReactiveFluentMongoOperations extends ReactiveFindOperation, ReactiveInsertOperation,
|
||||
ReactiveUpdateOperation, ReactiveRemoveOperation, ReactiveAggregationOperation, ReactiveMapReduceOperation, ReactiveChangeStreamOperation {}
|
||||
ReactiveUpdateOperation, ReactiveRemoveOperation, ReactiveAggregationOperation, ReactiveMapReduceOperation {}
|
||||
|
||||
@@ -40,7 +40,6 @@ import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.transaction.reactive.TransactionalOperator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -221,9 +220,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* {@link ClientSession#abortTransaction() rolled back} upon errors.
|
||||
*
|
||||
* @return new instance of {@link ReactiveSessionScoped}. Never {@literal null}.
|
||||
* @deprecated since 2.2. Use {@code @Transactional} or {@link TransactionalOperator}.
|
||||
*/
|
||||
@Deprecated
|
||||
ReactiveSessionScoped inTransaction();
|
||||
|
||||
/**
|
||||
@@ -238,9 +235,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* @param sessionProvider must not be {@literal null}.
|
||||
* @return new instance of {@link ReactiveSessionScoped}. Never {@literal null}.
|
||||
* @since 2.1
|
||||
* @deprecated since 2.2. Use {@code @Transactional} or {@link TransactionalOperator}.
|
||||
*/
|
||||
@Deprecated
|
||||
ReactiveSessionScoped inTransaction(Publisher<ClientSession> sessionProvider);
|
||||
|
||||
/**
|
||||
@@ -624,52 +619,24 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* entity mapping information to determine the collection the query is ran against. Note, that MongoDB limits the
|
||||
* number of results by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect a
|
||||
* particular number of results.
|
||||
* <p>
|
||||
* MongoDB 4.2 has removed the {@code geoNear} command. This method uses since version 2.2 aggregations and the
|
||||
* {@code $geoNear} aggregation command to emulate {@code geoNear} command functionality. We recommend using
|
||||
* aggregations directly:
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* TypedAggregation<T> geoNear = TypedAggregation.newAggregation(entityClass, Aggregation.geoNear(near, "dis"))
|
||||
* .withOptions(AggregationOptions.builder().collation(near.getCollation()).build());
|
||||
* Flux<Document> results = aggregate(geoNear, Document.class);
|
||||
* </pre>
|
||||
*
|
||||
* @param near must not be {@literal null}.
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return the converted {@link GeoResult}s.
|
||||
* @deprecated since 2.2. The {@code eval} command has been removed in MongoDB Server 4.2.0. Use Aggregations with
|
||||
* {@link Aggregation#geoNear(NearQuery, String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
<T> Flux<GeoResult<T>> geoNear(NearQuery near, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Returns {@link Flux} of {@link GeoResult} for all entities matching the given {@link NearQuery}. Note, that MongoDB
|
||||
* limits the number of results by default. Make sure to add an explicit limit to the {@link NearQuery} if you expect
|
||||
* a particular number of results.
|
||||
* <p>
|
||||
* MongoDB 4.2 has removed the {@code geoNear} command. This method uses since version 2.2 aggregations and the
|
||||
* {@code $geoNear} aggregation command to emulate {@code geoNear} command functionality. We recommend using
|
||||
* aggregations directly:
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* TypedAggregation<T> geoNear = TypedAggregation.newAggregation(entityClass, Aggregation.geoNear(near, "dis"))
|
||||
* .withOptions(AggregationOptions.builder().collation(near.getCollation()).build());
|
||||
* Flux<Document> results = aggregate(geoNear, Document.class);
|
||||
* </pre>
|
||||
*
|
||||
* @param near must not be {@literal null}.
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @param collectionName the collection to trigger the query against. If no collection name is given the entity class
|
||||
* will be inspected.
|
||||
* @return the converted {@link GeoResult}s.
|
||||
* @deprecated since 2.2. The {@code eval} command has been removed in MongoDB Server 4.2.0. Use Aggregations with
|
||||
* {@link Aggregation#geoNear(NearQuery, String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
<T> Flux<GeoResult<T>> geoNear(NearQuery near, Class<T> entityClass, String collectionName);
|
||||
|
||||
/**
|
||||
@@ -920,11 +887,6 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
|
||||
* <br />
|
||||
* <strong>NOTE:</strong> Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
|
||||
* influence on the resulting number of documents found as those values are passed on to the server and potentially
|
||||
* limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to
|
||||
* count all matches.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
|
||||
* {@literal null}.
|
||||
@@ -936,11 +898,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
|
||||
* must solely consist of document field references as we lack type information to map potential property references
|
||||
* onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support. <br />
|
||||
* <strong>NOTE:</strong> Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
|
||||
* influence on the resulting number of documents found as those values are passed on to the server and potentially
|
||||
* limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to
|
||||
* count all matches.
|
||||
* onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the criteria used to find documents.
|
||||
* @param collectionName must not be {@literal null} or empty.
|
||||
@@ -951,11 +909,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
|
||||
/**
|
||||
* Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
|
||||
* class to map the given {@link Query}. <br />
|
||||
* <strong>NOTE:</strong> Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
|
||||
* influence on the resulting number of documents found as those values are passed on to the server and potentially
|
||||
* limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to
|
||||
* count all matches.
|
||||
* class to map the given {@link Query}.
|
||||
*
|
||||
* @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
|
||||
* {@literal null}.
|
||||
@@ -973,8 +927,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's
|
||||
* Type Conversion"</a> for more details.
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's Type
|
||||
* Conversion"</a> for more details.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Insert is used to initially store the object into the database. To update an existing object use the save method.
|
||||
@@ -1033,8 +987,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's
|
||||
* Type Conversion"</a> for more details.
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's Type
|
||||
* Conversion"</a> for more details.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Insert is used to initially store the object into the database. To update an existing object use the save method.
|
||||
@@ -1081,8 +1035,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's
|
||||
* Type Conversion"</a> for more details.
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's Type
|
||||
* Conversion"</a> for more details.
|
||||
*
|
||||
* @param objectToSave the object to store in the collection. Must not be {@literal null}.
|
||||
* @return the saved object.
|
||||
@@ -1118,8 +1072,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
|
||||
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
|
||||
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's
|
||||
* Type Conversion"</a> for more details.
|
||||
* <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation" > Spring's Type
|
||||
* Conversion"</a> for more details.
|
||||
*
|
||||
* @param objectToSave the object to store in the collection. Must not be {@literal null}.
|
||||
* @return the saved object.
|
||||
@@ -1216,7 +1170,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* domain type information. Use {@link #updateFirst(Query, Update, Class, String)} to get full type specific support.
|
||||
* <br />
|
||||
* <strong>NOTE:</strong> {@link Query#getSortObject() sorting} is not supported by {@code db.collection.updateOne}.
|
||||
* Use {@link #findAndModify(Query, UpdateDefinition, Class, String)} instead.
|
||||
* Use {@link #findAndModify(Query, Update, Class, String)} instead.
|
||||
*
|
||||
* @param query the query document that specifies the criteria used to select a record to be updated. Must not be
|
||||
* {@literal null}.
|
||||
@@ -1535,7 +1489,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
/**
|
||||
* Returns the underlying {@link MongoConverter}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
MongoConverter getConverter();
|
||||
|
||||
@@ -1543,7 +1497,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
|
||||
* The collection name used for the specified class by this template.
|
||||
*
|
||||
* @param entityClass must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @since 2.1
|
||||
*/
|
||||
String getCollectionName(Class<?> entityClass);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -123,7 +123,7 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
|
||||
|
||||
String collectionName = getCollectionName();
|
||||
|
||||
return template.findAndModify(query, update, findAndModifyOptions != null ? findAndModifyOptions : FindAndModifyOptions.none(), targetType, collectionName);
|
||||
return template.findAndModify(query, update, findAndModifyOptions, targetType, collectionName);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -133,7 +133,7 @@ class ReactiveUpdateOperationSupport implements ReactiveUpdateOperation {
|
||||
@Override
|
||||
public Mono<T> findAndReplace() {
|
||||
return template.findAndReplace(query, replacement,
|
||||
findAndReplaceOptions != null ? findAndReplaceOptions : FindAndReplaceOptions.none(), (Class) domainType,
|
||||
findAndReplaceOptions != null ? findAndReplaceOptions : new FindAndReplaceOptions(), (Class) domainType,
|
||||
getCollectionName(), targetType);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import com.mongodb.ReadPreference;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by any object that wishes to expose the {@link ReadPreference}.
|
||||
* <p>
|
||||
* Typically implemented by cursor or query preparer objects.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 2.2
|
||||
*/
|
||||
public interface ReadPreferenceAware {
|
||||
|
||||
/**
|
||||
* @return {@literal true} if a {@link ReadPreference} is set.
|
||||
*/
|
||||
default boolean hasReadPreference() {
|
||||
return getReadPreference() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link ReadPreference} to apply or {@literal null} if none set.
|
||||
*/
|
||||
@Nullable
|
||||
ReadPreference getReadPreference();
|
||||
}
|
||||
@@ -29,9 +29,7 @@ import com.mongodb.DB;
|
||||
* @author Christoph Strobl
|
||||
* @author Oliver Gierke
|
||||
* @since 1.7
|
||||
* @deprecated since 2.2. The {@code eval} command has been removed without replacement in MongoDB Server 4.2.0.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ScriptOperations {
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,9 @@ import com.mongodb.ClientSessionOptions;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.mongodb.WriteConcern;
|
||||
import com.mongodb.client.ClientSession;
|
||||
import com.mongodb.client.MongoCollection;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
|
||||
/**
|
||||
@@ -33,9 +35,7 @@ import com.mongodb.client.MongoDatabase;
|
||||
* @author Christoph Strobl
|
||||
* @author George Moraitis
|
||||
* @author Mark Paluch
|
||||
* @deprecated since 2.2 in favor of {@link SimpleMongoClientDbFactory}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class SimpleMongoDbFactory extends MongoDbFactorySupport<MongoClient> implements DisposableBean {
|
||||
|
||||
/**
|
||||
|
||||
@@ -211,15 +211,6 @@ public class SimpleReactiveMongoDatabaseFactory implements DisposableBean, React
|
||||
return delegate.withSession(session);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.ReactiveMongoDatabaseFactory#isTransactionActive()
|
||||
*/
|
||||
@Override
|
||||
public boolean isTransactionActive() {
|
||||
return session != null && session.hasActiveTransaction();
|
||||
}
|
||||
|
||||
private MongoDatabase decorateDatabase(MongoDatabase database) {
|
||||
return createProxyInstance(session, database, MongoDatabase.class);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
/**
|
||||
* Enum to represent how strict the check of {@link com.mongodb.WriteConcernResult} shall be. It can either be skipped
|
||||
* entirely (use {@link #NONE}) or cause an exception to be thrown {@link #EXCEPTION}.
|
||||
* Enum to represent how strict the check of {@link com.mongodb.WriteResult} shall be. It can either be skipped entirely
|
||||
* (use {@link #NONE}) or cause an exception to be thrown {@link #EXCEPTION}.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Oliver Gierke
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -101,14 +100,14 @@ abstract class AbstractAggregationExpression implements AggregationExpression {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected List<Object> append(Object value, Expand expandList) {
|
||||
protected List<Object> append(Object value) {
|
||||
|
||||
if (this.value instanceof List) {
|
||||
|
||||
List<Object> clone = new ArrayList<Object>((List) this.value);
|
||||
|
||||
if (value instanceof Collection && Expand.EXPAND_VALUES.equals(expandList)) {
|
||||
clone.addAll((Collection<?>) value);
|
||||
if (value instanceof List) {
|
||||
clone.addAll((List) value);
|
||||
} else {
|
||||
clone.add(value);
|
||||
}
|
||||
@@ -118,17 +117,6 @@ abstract class AbstractAggregationExpression implements AggregationExpression {
|
||||
return Arrays.asList(this.value, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand a nested list of values to single entries or keep the list.
|
||||
*/
|
||||
protected enum Expand {
|
||||
EXPAND_VALUES, KEEP_SOURCE
|
||||
}
|
||||
|
||||
protected List<Object> append(Object value) {
|
||||
return append(value, Expand.EXPAND_VALUES);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected java.util.Map<String, Object> append(String key, Object value) {
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ public class AccumulatorOperators {
|
||||
* Take the numeric value referenced by given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link AccumulatorOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static AccumulatorOperatorFactory valueOf(String fieldReference) {
|
||||
return new AccumulatorOperatorFactory(fieldReference);
|
||||
@@ -44,7 +44,7 @@ public class AccumulatorOperators {
|
||||
* Take the numeric value referenced resulting from given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link AccumulatorOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static AccumulatorOperatorFactory valueOf(AggregationExpression expression) {
|
||||
return new AccumulatorOperatorFactory(expression);
|
||||
@@ -86,7 +86,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates and
|
||||
* returns the sum.
|
||||
*
|
||||
* @return new instance of {@link Sum}.
|
||||
* @return
|
||||
*/
|
||||
public Sum sum() {
|
||||
return usesFieldRef() ? Sum.sumOf(fieldReference) : Sum.sumOf(expression);
|
||||
@@ -96,7 +96,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the
|
||||
* average value.
|
||||
*
|
||||
* @return new instance of {@link Avg}.
|
||||
* @return
|
||||
*/
|
||||
public Avg avg() {
|
||||
return usesFieldRef() ? Avg.avgOf(fieldReference) : Avg.avgOf(expression);
|
||||
@@ -106,7 +106,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the
|
||||
* maximum value.
|
||||
*
|
||||
* @return new instance of {@link Max}.
|
||||
* @return
|
||||
*/
|
||||
public Max max() {
|
||||
return usesFieldRef() ? Max.maxOf(fieldReference) : Max.maxOf(expression);
|
||||
@@ -116,7 +116,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and returns the
|
||||
* minimum value.
|
||||
*
|
||||
* @return new instance of {@link Min}.
|
||||
* @return
|
||||
*/
|
||||
public Min min() {
|
||||
return usesFieldRef() ? Min.minOf(fieldReference) : Min.minOf(expression);
|
||||
@@ -126,7 +126,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates the
|
||||
* population standard deviation of the input values.
|
||||
*
|
||||
* @return new instance of {@link StdDevPop}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevPop stdDevPop() {
|
||||
return usesFieldRef() ? StdDevPop.stdDevPopOf(fieldReference) : StdDevPop.stdDevPopOf(expression);
|
||||
@@ -136,7 +136,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link AggregationExpression} that takes the associated numeric value expression and calculates the
|
||||
* sample standard deviation of the input values.
|
||||
*
|
||||
* @return new instance of {@link StdDevSamp}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevSamp stdDevSamp() {
|
||||
return usesFieldRef() ? StdDevSamp.stdDevSampOf(fieldReference) : StdDevSamp.stdDevSampOf(expression);
|
||||
@@ -167,7 +167,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Sum}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Sum}.
|
||||
* @return
|
||||
*/
|
||||
public static Sum sumOf(String fieldReference) {
|
||||
|
||||
@@ -179,7 +179,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Sum}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Sum}.
|
||||
* @return
|
||||
*/
|
||||
public static Sum sumOf(AggregationExpression expression) {
|
||||
|
||||
@@ -192,7 +192,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Sum}.
|
||||
* @return
|
||||
*/
|
||||
public Sum and(String fieldReference) {
|
||||
|
||||
@@ -205,7 +205,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Sum}.
|
||||
* @return
|
||||
*/
|
||||
public Sum and(AggregationExpression expression) {
|
||||
|
||||
@@ -213,20 +213,6 @@ public class AccumulatorOperators {
|
||||
return new Sum(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link Sum} with all previously added arguments appending the given one. <br />
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param value the value to add.
|
||||
* @return new instance of {@link Sum}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public Sum and(Number value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return new Sum(append(value));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.aggregation.AccumulatorOperators.AbstractAggregationExpression#toDocument(java.lang.Object, org.springframework.data.mongodb.core.aggregation.AggregationOperationContext)
|
||||
*/
|
||||
@@ -264,7 +250,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Avg}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Avg}.
|
||||
* @return
|
||||
*/
|
||||
public static Avg avgOf(String fieldReference) {
|
||||
|
||||
@@ -276,7 +262,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Avg}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Avg}.
|
||||
* @return
|
||||
*/
|
||||
public static Avg avgOf(AggregationExpression expression) {
|
||||
|
||||
@@ -289,7 +275,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Avg}.
|
||||
* @return
|
||||
*/
|
||||
public Avg and(String fieldReference) {
|
||||
|
||||
@@ -302,7 +288,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Avg}.
|
||||
* @return
|
||||
*/
|
||||
public Avg and(AggregationExpression expression) {
|
||||
|
||||
@@ -347,7 +333,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Max}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Max}.
|
||||
* @return
|
||||
*/
|
||||
public static Max maxOf(String fieldReference) {
|
||||
|
||||
@@ -359,7 +345,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Max}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Max}.
|
||||
* @return
|
||||
*/
|
||||
public static Max maxOf(AggregationExpression expression) {
|
||||
|
||||
@@ -372,7 +358,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Max}.
|
||||
* @return
|
||||
*/
|
||||
public Max and(String fieldReference) {
|
||||
|
||||
@@ -385,7 +371,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Max}.
|
||||
* @return
|
||||
*/
|
||||
public Max and(AggregationExpression expression) {
|
||||
|
||||
@@ -430,7 +416,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Min}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Min}.
|
||||
* @return
|
||||
*/
|
||||
public static Min minOf(String fieldReference) {
|
||||
|
||||
@@ -442,7 +428,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link Min}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Min}.
|
||||
* @return
|
||||
*/
|
||||
public static Min minOf(AggregationExpression expression) {
|
||||
|
||||
@@ -455,7 +441,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Min}.
|
||||
* @return
|
||||
*/
|
||||
public Min and(String fieldReference) {
|
||||
|
||||
@@ -468,7 +454,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Min}.
|
||||
* @return
|
||||
*/
|
||||
public Min and(AggregationExpression expression) {
|
||||
|
||||
@@ -513,7 +499,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link StdDevPop}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevPop}.
|
||||
* @return
|
||||
*/
|
||||
public static StdDevPop stdDevPopOf(String fieldReference) {
|
||||
|
||||
@@ -525,7 +511,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link StdDevPop} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevPop}.
|
||||
* @return
|
||||
*/
|
||||
public static StdDevPop stdDevPopOf(AggregationExpression expression) {
|
||||
|
||||
@@ -538,7 +524,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevPop}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevPop and(String fieldReference) {
|
||||
|
||||
@@ -551,7 +537,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevPop}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevPop and(AggregationExpression expression) {
|
||||
|
||||
@@ -596,7 +582,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link StdDevSamp}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevSamp}.
|
||||
* @return
|
||||
*/
|
||||
public static StdDevSamp stdDevSampOf(String fieldReference) {
|
||||
|
||||
@@ -608,7 +594,7 @@ public class AccumulatorOperators {
|
||||
* Creates new {@link StdDevSamp}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevSamp}.
|
||||
* @return
|
||||
*/
|
||||
public static StdDevSamp stdDevSampOf(AggregationExpression expression) {
|
||||
|
||||
@@ -621,7 +607,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevSamp}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevSamp and(String fieldReference) {
|
||||
|
||||
@@ -634,7 +620,7 @@ public class AccumulatorOperators {
|
||||
* <strong>NOTE:</strong> Only possible in {@code $project} stage.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link StdDevSamp}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevSamp and(AggregationExpression expression) {
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ public class Aggregation {
|
||||
* supported in MongoDB version 2.6+.
|
||||
*
|
||||
* @param options must not be {@literal null}.
|
||||
* @return new instance of {@link Aggregation}.
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
public Aggregation withOptions(AggregationOptions options) {
|
||||
@@ -228,7 +228,7 @@ public class Aggregation {
|
||||
* Creates a new {@link ProjectionOperation} including the given fields.
|
||||
*
|
||||
* @param fields must not be {@literal null}.
|
||||
* @return new instance of {@link ProjectionOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static ProjectionOperation project(String... fields) {
|
||||
return project(fields(fields));
|
||||
@@ -238,30 +238,17 @@ public class Aggregation {
|
||||
* Creates a new {@link ProjectionOperation} including the given {@link Fields}.
|
||||
*
|
||||
* @param fields must not be {@literal null}.
|
||||
* @return new instance of {@link ProjectionOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static ProjectionOperation project(Fields fields) {
|
||||
return new ProjectionOperation(fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ProjectionOperation} including all top level fields of the given given {@link Class}.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return new instance of {@link ProjectionOperation}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static ProjectionOperation project(Class<?> type) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
return new ProjectionOperation(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a new {@link UnwindOperation} for the field with the given name.
|
||||
*
|
||||
* @param field must not be {@literal null} or empty.
|
||||
* @return new instance of {@link UnwindOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static UnwindOperation unwind(String field) {
|
||||
return new UnwindOperation(field(field));
|
||||
@@ -271,7 +258,7 @@ public class Aggregation {
|
||||
* Factory method to create a new {@link ReplaceRootOperation} for the field with the given name.
|
||||
*
|
||||
* @param fieldName must not be {@literal null} or empty.
|
||||
* @return new instance of {@link ReplaceRootOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static ReplaceRootOperation replaceRoot(String fieldName) {
|
||||
@@ -283,7 +270,7 @@ public class Aggregation {
|
||||
* {@link AggregationExpression}.
|
||||
*
|
||||
* @param aggregationExpression must not be {@literal null}.
|
||||
* @return new instance of {@link ReplaceRootOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static ReplaceRootOperation replaceRoot(AggregationExpression aggregationExpression) {
|
||||
@@ -349,7 +336,7 @@ public class Aggregation {
|
||||
* Creates a new {@link GroupOperation} for the given fields.
|
||||
*
|
||||
* @param fields must not be {@literal null}.
|
||||
* @return new instance of {@link GroupOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static GroupOperation group(String... fields) {
|
||||
return group(fields(fields));
|
||||
@@ -370,7 +357,7 @@ public class Aggregation {
|
||||
* {@link GraphLookupOperation} given {@literal fromCollection}.
|
||||
*
|
||||
* @param fromCollection must not be {@literal null} or empty.
|
||||
* @return new instance of {@link StartWithBuilder} for creating a {@link GraphLookupOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static StartWithBuilder graphLookup(String fromCollection) {
|
||||
@@ -381,7 +368,7 @@ public class Aggregation {
|
||||
* Factory method to create a new {@link SortOperation} for the given {@link Sort}.
|
||||
*
|
||||
* @param sort must not be {@literal null}.
|
||||
* @return new instance of {@link SortOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static SortOperation sort(Sort sort) {
|
||||
return new SortOperation(sort);
|
||||
@@ -392,7 +379,7 @@ public class Aggregation {
|
||||
*
|
||||
* @param direction must not be {@literal null}.
|
||||
* @param fields must not be {@literal null}.
|
||||
* @return new instance of {@link SortOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static SortOperation sort(Direction direction, String... fields) {
|
||||
return new SortOperation(Sort.by(direction, fields));
|
||||
@@ -402,7 +389,7 @@ public class Aggregation {
|
||||
* Creates a new {@link SortByCountOperation} given {@literal groupByField}.
|
||||
*
|
||||
* @param field must not be {@literal null} or empty.
|
||||
* @return new instance of {@link SortByCountOperation}.
|
||||
* @return
|
||||
* @since 2.1
|
||||
*/
|
||||
public static SortByCountOperation sortByCount(String field) {
|
||||
@@ -413,7 +400,7 @@ public class Aggregation {
|
||||
* Creates a new {@link SortByCountOperation} given {@link AggregationExpression group and sort expression}.
|
||||
*
|
||||
* @param groupAndSortExpression must not be {@literal null}.
|
||||
* @return new instance of {@link SortByCountOperation}.
|
||||
* @return
|
||||
* @since 2.1
|
||||
*/
|
||||
public static SortByCountOperation sortByCount(AggregationExpression groupAndSortExpression) {
|
||||
@@ -424,10 +411,9 @@ public class Aggregation {
|
||||
* Creates a new {@link SkipOperation} skipping the given number of elements.
|
||||
*
|
||||
* @param elementsToSkip must not be less than zero.
|
||||
* @return new instance of {@link SkipOperation}.
|
||||
* @return
|
||||
* @deprecated prepare to get this one removed in favor of {@link #skip(long)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static SkipOperation skip(int elementsToSkip) {
|
||||
return new SkipOperation(elementsToSkip);
|
||||
}
|
||||
@@ -436,7 +422,7 @@ public class Aggregation {
|
||||
* Creates a new {@link SkipOperation} skipping the given number of elements.
|
||||
*
|
||||
* @param elementsToSkip must not be less than zero.
|
||||
* @return new instance of {@link SkipOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static SkipOperation skip(long elementsToSkip) {
|
||||
return new SkipOperation(elementsToSkip);
|
||||
@@ -446,7 +432,7 @@ public class Aggregation {
|
||||
* Creates a new {@link LimitOperation} limiting the result to the given number of elements.
|
||||
*
|
||||
* @param maxElements must not be less than zero.
|
||||
* @return new instance of {@link LimitOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static LimitOperation limit(long maxElements) {
|
||||
return new LimitOperation(maxElements);
|
||||
@@ -456,7 +442,7 @@ public class Aggregation {
|
||||
* Creates a new {@link SampleOperation} to select the specified number of documents from its input randomly.
|
||||
*
|
||||
* @param sampleSize must not be less than zero.
|
||||
* @return new instance of {@link SampleOperation}.
|
||||
* @return
|
||||
* @since 2.0
|
||||
*/
|
||||
public static SampleOperation sample(long sampleSize) {
|
||||
@@ -467,7 +453,7 @@ public class Aggregation {
|
||||
* Creates a new {@link MatchOperation} using the given {@link Criteria}.
|
||||
*
|
||||
* @param criteria must not be {@literal null}.
|
||||
* @return new instance of {@link MatchOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static MatchOperation match(Criteria criteria) {
|
||||
return new MatchOperation(criteria);
|
||||
@@ -477,7 +463,7 @@ public class Aggregation {
|
||||
* Creates a new {@link MatchOperation} using the given {@link CriteriaDefinition}.
|
||||
*
|
||||
* @param criteria must not be {@literal null}.
|
||||
* @return new instance of {@link MatchOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static MatchOperation match(CriteriaDefinition criteria) {
|
||||
@@ -492,7 +478,7 @@ public class Aggregation {
|
||||
* collection in the current database if one does not already exist. The collection is not visible until the
|
||||
* aggregation completes. If the aggregation fails, MongoDB does not create the collection. Must not be
|
||||
* {@literal null}.
|
||||
* @return new instance of {@link OutOperation}.
|
||||
* @return
|
||||
*/
|
||||
public static OutOperation out(String outCollectionName) {
|
||||
return new OutOperation(outCollectionName);
|
||||
@@ -502,7 +488,7 @@ public class Aggregation {
|
||||
* Creates a new {@link BucketOperation} given {@literal groupByField}.
|
||||
*
|
||||
* @param groupByField must not be {@literal null} or empty.
|
||||
* @return new instance of {@link BucketOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static BucketOperation bucket(String groupByField) {
|
||||
@@ -513,7 +499,7 @@ public class Aggregation {
|
||||
* Creates a new {@link BucketOperation} given {@link AggregationExpression group-by expression}.
|
||||
*
|
||||
* @param groupByExpression must not be {@literal null}.
|
||||
* @return new instance of {@link BucketOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static BucketOperation bucket(AggregationExpression groupByExpression) {
|
||||
@@ -525,7 +511,7 @@ public class Aggregation {
|
||||
*
|
||||
* @param groupByField must not be {@literal null} or empty.
|
||||
* @param buckets number of buckets, must be a positive integer.
|
||||
* @return new instance of {@link BucketAutoOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static BucketAutoOperation bucketAuto(String groupByField, int buckets) {
|
||||
@@ -537,7 +523,7 @@ public class Aggregation {
|
||||
*
|
||||
* @param groupByExpression must not be {@literal null}.
|
||||
* @param buckets number of buckets, must be a positive integer.
|
||||
* @return new instance of {@link BucketAutoOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static BucketAutoOperation bucketAuto(AggregationExpression groupByExpression, int buckets) {
|
||||
@@ -547,7 +533,7 @@ public class Aggregation {
|
||||
/**
|
||||
* Creates a new {@link FacetOperation}.
|
||||
*
|
||||
* @return new instance of {@link FacetOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static FacetOperation facet() {
|
||||
@@ -558,7 +544,7 @@ public class Aggregation {
|
||||
* Creates a new {@link FacetOperationBuilder} given {@link Aggregation}.
|
||||
*
|
||||
* @param aggregationOperations the sub-pipeline, must not be {@literal null}.
|
||||
* @return new instance of {@link FacetOperation}.
|
||||
* @return
|
||||
* @since 1.10
|
||||
*/
|
||||
public static FacetOperationBuilder facet(AggregationOperation... aggregationOperations) {
|
||||
@@ -607,7 +593,7 @@ public class Aggregation {
|
||||
* Creates a new {@link Fields} instance for the given field names.
|
||||
*
|
||||
* @param fields must not be {@literal null}.
|
||||
* @return new instance of {@link Fields}.
|
||||
* @return
|
||||
* @see Fields#fields(String...)
|
||||
*/
|
||||
public static Fields fields(String... fields) {
|
||||
@@ -619,14 +605,14 @@ public class Aggregation {
|
||||
*
|
||||
* @param name must not be {@literal null} or empty.
|
||||
* @param target must not be {@literal null} or empty.
|
||||
* @return new instance of {@link Fields}.
|
||||
* @return
|
||||
*/
|
||||
public static Fields bind(String name, String target) {
|
||||
return Fields.from(field(name, target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the {@code distanceField}. The
|
||||
* Creates a new {@link GeoNearOperation} instance from the given {@link NearQuery} and the{@code distanceField}. The
|
||||
* {@code distanceField} defines output field that contains the calculated distance.
|
||||
*
|
||||
* @param query must not be {@literal null}.
|
||||
@@ -641,7 +627,7 @@ public class Aggregation {
|
||||
/**
|
||||
* Returns a new {@link AggregationOptions.Builder}.
|
||||
*
|
||||
* @return new instance of {@link AggregationOptions.Builder}.
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
public static AggregationOptions.Builder newAggregationOptions() {
|
||||
@@ -703,7 +689,7 @@ public class Aggregation {
|
||||
* otherwise.
|
||||
*
|
||||
* @param fieldRef may be {@literal null}.
|
||||
* @return {@literal true} if the given field refers to a {@link SystemVariable}.
|
||||
* @return
|
||||
*/
|
||||
public static boolean isReferingToSystemVariable(@Nullable String fieldRef) {
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ public interface AggregationExpression {
|
||||
* Turns the {@link AggregationExpression} into a {@link Document} within the given
|
||||
* {@link AggregationOperationContext}.
|
||||
*
|
||||
* @param context must not be {@literal null}.
|
||||
* @return the MongoDB native ({@link Document}) form of the expression.
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
Document toDocument(AggregationOperationContext context);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ interface AggregationExpressionTransformer
|
||||
* @param currentNode must not be {@literal null}.
|
||||
* @param parentNode may be {@literal null}.
|
||||
* @param previousOperationObject may be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @param aggregationContext must not be {@literal null}.
|
||||
*/
|
||||
public AggregationExpressionTransformationContext(T currentNode, @Nullable ExpressionNode parentNode,
|
||||
@Nullable Document previousOperationObject, AggregationOperationContext context) {
|
||||
@@ -67,7 +67,7 @@ interface AggregationExpressionTransformer
|
||||
/**
|
||||
* Returns the underlying {@link AggregationOperationContext}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public AggregationOperationContext getAggregationContext() {
|
||||
return aggregationContext;
|
||||
@@ -76,7 +76,7 @@ interface AggregationExpressionTransformer
|
||||
/**
|
||||
* Returns the {@link FieldReference} for the current {@link ExpressionNode}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public FieldReference getFieldReference() {
|
||||
return aggregationContext.getReference(getCurrentNode().getName());
|
||||
|
||||
@@ -41,7 +41,7 @@ public enum AggregationFunctionExpressions {
|
||||
* Returns an {@link AggregationExpression} build from the current {@link Enum} name and the given parameters.
|
||||
*
|
||||
* @param parameters must not be {@literal null}
|
||||
* @return new instance of {@link AggregationExpression}.
|
||||
* @return
|
||||
*/
|
||||
public AggregationExpression of(Object... parameters) {
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
@@ -35,23 +32,7 @@ public interface AggregationOperation {
|
||||
* Turns the {@link AggregationOperation} into a {@link Document} by using the given
|
||||
* {@link AggregationOperationContext}.
|
||||
*
|
||||
* @param context the {@link AggregationOperationContext} to operate within. Must not be {@literal null}.
|
||||
* @return the Document
|
||||
* @deprecated since 2.2 in favor of {@link #toPipelineStages(AggregationOperationContext)}.
|
||||
*/
|
||||
@Deprecated
|
||||
Document toDocument(AggregationOperationContext context);
|
||||
|
||||
/**
|
||||
* Turns the {@link AggregationOperation} into list of {@link Document stages} by using the given
|
||||
* {@link AggregationOperationContext}. This allows a single {@link AggregationOptions} to add additional stages for
|
||||
* eg. {@code $sort} or {@code $limit}.
|
||||
*
|
||||
* @param context the {@link AggregationOperationContext} to operate within. Must not be {@literal null}.
|
||||
* @return the pipeline stages to run through. Never {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
default List<Document> toPipelineStages(AggregationOperationContext context) {
|
||||
return Collections.singletonList(toDocument(context));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* The context for an {@link AggregationOperation}.
|
||||
@@ -42,65 +33,23 @@ public interface AggregationOperationContext {
|
||||
* @param document will never be {@literal null}.
|
||||
* @return must not be {@literal null}.
|
||||
*/
|
||||
default Document getMappedObject(Document document) {
|
||||
return getMappedObject(document, null);
|
||||
}
|
||||
Document getMappedObject(Document document);
|
||||
|
||||
/**
|
||||
* Returns the mapped {@link Document}, potentially converting the source considering mapping metadata for the given
|
||||
* type.
|
||||
*
|
||||
* @param document will never be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
* @return must not be {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
Document getMappedObject(Document document, @Nullable Class<?> type);
|
||||
|
||||
/**
|
||||
* Returns a {@link FieldReference} for the given field.
|
||||
* Returns a {@link FieldReference} for the given field or {@literal null} if the context does not expose the given
|
||||
* field.
|
||||
*
|
||||
* @param field must not be {@literal null}.
|
||||
* @return the {@link FieldReference} for the given {@link Field}.
|
||||
* @throws IllegalArgumentException if the context does not expose a field with the given name
|
||||
* @return
|
||||
*/
|
||||
FieldReference getReference(Field field);
|
||||
|
||||
/**
|
||||
* Returns the {@link FieldReference} for the field with the given name.
|
||||
* Returns the {@link FieldReference} for the field with the given name or {@literal null} if the context does not
|
||||
* expose a field with the given name.
|
||||
*
|
||||
* @param name must not be {@literal null} or empty.
|
||||
* @return the {@link FieldReference} for the field with given {@literal name}.
|
||||
* @throws IllegalArgumentException if the context does not expose a field with the given name
|
||||
* @return
|
||||
*/
|
||||
FieldReference getReference(String name);
|
||||
|
||||
/**
|
||||
* Returns the {@link Fields} exposed by the type. May be a {@literal class} or an {@literal interface}. The default
|
||||
* implementation uses {@link BeanUtils#getPropertyDescriptors(Class) property descriptors} discover fields from a
|
||||
* {@link Class}.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @since 2.2
|
||||
* @see BeanUtils#getPropertyDescriptor(Class, String)
|
||||
*/
|
||||
default Fields getFields(Class<?> type) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
|
||||
return Fields.fields(Arrays.stream(BeanUtils.getPropertyDescriptors(type)) //
|
||||
.filter(it -> { // object and default methods
|
||||
Method method = it.getReadMethod();
|
||||
if (method == null) {
|
||||
return false;
|
||||
}
|
||||
if (ReflectionUtils.isObjectMethod(method)) {
|
||||
return false;
|
||||
}
|
||||
return !method.isDefault();
|
||||
}) //
|
||||
.map(PropertyDescriptor::getName) //
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedFi
|
||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.FieldReference;
|
||||
import org.springframework.data.mongodb.core.aggregation.Fields.AggregationField;
|
||||
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Rendering support for {@link AggregationOperation} into a {@link List} of {@link org.bson.Document}.
|
||||
@@ -53,7 +52,7 @@ class AggregationOperationRenderer {
|
||||
|
||||
for (AggregationOperation operation : operations) {
|
||||
|
||||
operationDocuments.addAll(operation.toPipelineStages(contextToUse));
|
||||
operationDocuments.add(operation.toDocument(contextToUse));
|
||||
|
||||
if (operation instanceof FieldsExposingAggregationOperation) {
|
||||
|
||||
@@ -76,16 +75,15 @@ class AggregationOperationRenderer {
|
||||
* Simple {@link AggregationOperationContext} that just returns {@link FieldReference}s as is.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
private static class NoOpAggregationOperationContext implements AggregationOperationContext {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(org.bson.Document, java.lang.Class)
|
||||
* @see org.springframework.data.mongodb.core.aggregation.AggregationOperationContext#getMappedObject(org.bson.Document)
|
||||
*/
|
||||
@Override
|
||||
public Document getMappedObject(Document document, @Nullable Class<?> type) {
|
||||
public Document getMappedObject(Document document) {
|
||||
return document;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,13 +44,11 @@ public class AggregationOptions {
|
||||
private static final String EXPLAIN = "explain";
|
||||
private static final String ALLOW_DISK_USE = "allowDiskUse";
|
||||
private static final String COLLATION = "collation";
|
||||
private static final String COMMENT = "comment";
|
||||
|
||||
private final boolean allowDiskUse;
|
||||
private final boolean explain;
|
||||
private final Optional<Document> cursor;
|
||||
private final Optional<Collation> collation;
|
||||
private final Optional<String> comment;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AggregationOptions}.
|
||||
@@ -75,28 +73,11 @@ public class AggregationOptions {
|
||||
*/
|
||||
public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor,
|
||||
@Nullable Collation collation) {
|
||||
this(allowDiskUse, explain, cursor, collation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link AggregationOptions}.
|
||||
*
|
||||
* @param allowDiskUse whether to off-load intensive sort-operations to disk.
|
||||
* @param explain whether to get the execution plan for the aggregation instead of the actual results.
|
||||
* @param cursor can be {@literal null}, used to pass additional options (such as {@code batchSize}) to the
|
||||
* aggregation.
|
||||
* @param collation collation for string comparison. Can be {@literal null}.
|
||||
* @param comment execution comment. Can be {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public AggregationOptions(boolean allowDiskUse, boolean explain, @Nullable Document cursor,
|
||||
@Nullable Collation collation, @Nullable String comment) {
|
||||
|
||||
this.allowDiskUse = allowDiskUse;
|
||||
this.explain = explain;
|
||||
this.cursor = Optional.ofNullable(cursor);
|
||||
this.collation = Optional.ofNullable(collation);
|
||||
this.comment = Optional.ofNullable(comment);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,9 +108,8 @@ public class AggregationOptions {
|
||||
Document cursor = document.get(CURSOR, Document.class);
|
||||
Collation collation = document.containsKey(COLLATION) ? Collation.from(document.get(COLLATION, Document.class))
|
||||
: null;
|
||||
String comment = document.getString(COMMENT);
|
||||
|
||||
return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
|
||||
return new AggregationOptions(allowDiskUse, explain, cursor, collation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +126,7 @@ public class AggregationOptions {
|
||||
* Enables writing to temporary files. When set to true, aggregation stages can write data to the _tmp subdirectory in
|
||||
* the dbPath directory.
|
||||
*
|
||||
* @return {@literal true} if enabled.
|
||||
* @return
|
||||
*/
|
||||
public boolean isAllowDiskUse() {
|
||||
return allowDiskUse;
|
||||
@@ -155,7 +135,7 @@ public class AggregationOptions {
|
||||
/**
|
||||
* Specifies to return the information on the processing of the pipeline.
|
||||
*
|
||||
* @return {@literal true} if enabled.
|
||||
* @return
|
||||
*/
|
||||
public boolean isExplain() {
|
||||
return explain;
|
||||
@@ -180,7 +160,7 @@ public class AggregationOptions {
|
||||
/**
|
||||
* Specify a document that contains options that control the creation of the cursor object.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public Optional<Document> getCursor() {
|
||||
return cursor;
|
||||
@@ -189,23 +169,13 @@ public class AggregationOptions {
|
||||
/**
|
||||
* Get collation settings for string comparison.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
* @since 2.0
|
||||
*/
|
||||
public Optional<Collation> getCollation() {
|
||||
return collation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the comment for the aggregation.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public Optional<String> getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new potentially adjusted copy for the given {@code aggregationCommandObject} with the configuration
|
||||
* applied.
|
||||
@@ -239,7 +209,7 @@ public class AggregationOptions {
|
||||
/**
|
||||
* Returns a {@link Document} representation of this {@link AggregationOptions}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public Document toDocument() {
|
||||
|
||||
@@ -249,7 +219,6 @@ public class AggregationOptions {
|
||||
|
||||
cursor.ifPresent(val -> document.put(CURSOR, val));
|
||||
collation.ifPresent(val -> document.append(COLLATION, val.toDocument()));
|
||||
comment.ifPresent(val -> document.append(COMMENT, val));
|
||||
|
||||
return document;
|
||||
}
|
||||
@@ -278,13 +247,12 @@ public class AggregationOptions {
|
||||
private boolean explain;
|
||||
private @Nullable Document cursor;
|
||||
private @Nullable Collation collation;
|
||||
private @Nullable String comment;
|
||||
|
||||
/**
|
||||
* Defines whether to off-load intensive sort-operations to disk.
|
||||
*
|
||||
* @param allowDiskUse use {@literal true} to allow disk use during the aggregation.
|
||||
* @return this.
|
||||
* @param allowDiskUse
|
||||
* @return
|
||||
*/
|
||||
public Builder allowDiskUse(boolean allowDiskUse) {
|
||||
|
||||
@@ -295,8 +263,8 @@ public class AggregationOptions {
|
||||
/**
|
||||
* Defines whether to get the execution plan for the aggregation instead of the actual results.
|
||||
*
|
||||
* @param explain use {@literal true} to enable explain feature.
|
||||
* @return this.
|
||||
* @param explain
|
||||
* @return
|
||||
*/
|
||||
public Builder explain(boolean explain) {
|
||||
|
||||
@@ -307,8 +275,8 @@ public class AggregationOptions {
|
||||
/**
|
||||
* Additional options to the aggregation.
|
||||
*
|
||||
* @param cursor must not be {@literal null}.
|
||||
* @return this.
|
||||
* @param cursor
|
||||
* @return
|
||||
*/
|
||||
public Builder cursor(Document cursor) {
|
||||
|
||||
@@ -319,8 +287,8 @@ public class AggregationOptions {
|
||||
/**
|
||||
* Define the initial cursor batch size.
|
||||
*
|
||||
* @param batchSize use a positive int.
|
||||
* @return this.
|
||||
* @param batchSize
|
||||
* @return
|
||||
* @since 2.0
|
||||
*/
|
||||
public Builder cursorBatchSize(int batchSize) {
|
||||
@@ -333,8 +301,7 @@ public class AggregationOptions {
|
||||
* Define collation settings for string comparison.
|
||||
*
|
||||
* @param collation can be {@literal null}.
|
||||
* @return this.
|
||||
* @since 2.0
|
||||
* @return
|
||||
*/
|
||||
public Builder collation(@Nullable Collation collation) {
|
||||
|
||||
@@ -342,26 +309,13 @@ public class AggregationOptions {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a comment to describe the execution.
|
||||
*
|
||||
* @param comment can be {@literal null}.
|
||||
* @return this.
|
||||
* @since 2.2
|
||||
*/
|
||||
public Builder comment(@Nullable String comment) {
|
||||
|
||||
this.comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link AggregationOptions} instance with the given configuration.
|
||||
*
|
||||
* @return new instance of {@link AggregationOptions}.
|
||||
* @return
|
||||
*/
|
||||
public AggregationOptions build() {
|
||||
return new AggregationOptions(allowDiskUse, explain, cursor, collation, comment);
|
||||
return new AggregationOptions(allowDiskUse, explain, cursor, collation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class AggregationResults<T> implements Iterable<T> {
|
||||
/**
|
||||
* Returns the aggregation results.
|
||||
*
|
||||
* @return the list of already mapped results or an empty one if none found.
|
||||
* @return
|
||||
*/
|
||||
public List<T> getMappedResults() {
|
||||
return mappedResults;
|
||||
@@ -68,7 +68,7 @@ public class AggregationResults<T> implements Iterable<T> {
|
||||
/**
|
||||
* Returns the unique mapped result. Assumes no result or exactly one.
|
||||
*
|
||||
* @return the single already mapped result object or raise an error if more than one found.
|
||||
* @return
|
||||
* @throws IllegalArgumentException in case more than one result is available.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -88,7 +88,7 @@ public class AggregationResults<T> implements Iterable<T> {
|
||||
/**
|
||||
* Returns the server that has been used to perform the aggregation.
|
||||
*
|
||||
* @return can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public String getServerUsed() {
|
||||
@@ -98,7 +98,7 @@ public class AggregationResults<T> implements Iterable<T> {
|
||||
/**
|
||||
* Returns the raw result that was returned by the server.
|
||||
*
|
||||
* @return the raw response.
|
||||
* @return
|
||||
* @since 1.6
|
||||
*/
|
||||
public Document getRawResults() {
|
||||
|
||||
@@ -56,7 +56,7 @@ public class AggregationSpELExpression implements AggregationExpression {
|
||||
*
|
||||
* @param expressionString must not be {@literal null}.
|
||||
* @param parameters can be empty.
|
||||
* @return new instance of {@link AggregationSpELExpression}.
|
||||
* @return
|
||||
*/
|
||||
public static AggregationSpELExpression expressionOf(String expressionString, Object... parameters) {
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ interface AggregationUtils {
|
||||
* Converts the given {@link Range} into an array of values.
|
||||
*
|
||||
* @param range must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
static List<Long> toRangeValues(Range<Long> range) {
|
||||
public static List<Long> toRangeValues(Range<Long> range) {
|
||||
|
||||
Assert.notNull(range, "Range must not be null!");
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class ArithmeticOperators {
|
||||
* Take the field referenced by given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ArithmeticOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ArithmeticOperatorFactory valueOf(String fieldReference) {
|
||||
return new ArithmeticOperatorFactory(fieldReference);
|
||||
@@ -48,7 +48,7 @@ public class ArithmeticOperators {
|
||||
* Take the value resulting from the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ArithmeticOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ArithmeticOperatorFactory valueOf(AggregationExpression expression) {
|
||||
return new ArithmeticOperatorFactory(expression);
|
||||
@@ -89,7 +89,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that returns the absolute value of the associated number.
|
||||
*
|
||||
* @return new instance of {@link Abs}.
|
||||
* @return
|
||||
*/
|
||||
public Abs abs() {
|
||||
return usesFieldRef() ? Abs.absoluteValueOf(fieldReference) : Abs.absoluteValueOf(expression);
|
||||
@@ -100,7 +100,7 @@ public class ArithmeticOperators {
|
||||
* number.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
* @return
|
||||
*/
|
||||
public Add add(String fieldReference) {
|
||||
|
||||
@@ -113,7 +113,7 @@ public class ArithmeticOperators {
|
||||
* {@link AggregationExpression} to the associated number.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
* @return
|
||||
*/
|
||||
public Add add(AggregationExpression expression) {
|
||||
|
||||
@@ -125,7 +125,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that adds the given {@literal value} to the associated number.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
* @return
|
||||
*/
|
||||
public Add add(Number value) {
|
||||
|
||||
@@ -141,7 +141,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that returns the smallest integer greater than or equal to the
|
||||
* assoicated number.
|
||||
*
|
||||
* @return new instance of {@link Ceil}.
|
||||
* @return
|
||||
*/
|
||||
public Ceil ceil() {
|
||||
return usesFieldRef() ? Ceil.ceilValueOf(fieldReference) : Ceil.ceilValueOf(expression);
|
||||
@@ -152,7 +152,7 @@ public class ArithmeticOperators {
|
||||
* {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
* @return
|
||||
*/
|
||||
public Divide divideBy(String fieldReference) {
|
||||
|
||||
@@ -165,7 +165,7 @@ public class ArithmeticOperators {
|
||||
* {@literal expression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
* @return
|
||||
*/
|
||||
public Divide divideBy(AggregationExpression expression) {
|
||||
|
||||
@@ -176,8 +176,8 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that divides the associated number by given {@literal value}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public Divide divideBy(Number value) {
|
||||
|
||||
@@ -192,7 +192,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that raises Euler’s number (i.e. e ) on the associated number.
|
||||
*
|
||||
* @return new instance of {@link Exp}.
|
||||
* @return
|
||||
*/
|
||||
public Exp exp() {
|
||||
return usesFieldRef() ? Exp.expValueOf(fieldReference) : Exp.expValueOf(expression);
|
||||
@@ -202,7 +202,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that returns the largest integer less than or equal to the associated
|
||||
* number.
|
||||
*
|
||||
* @return new instance of {@link Floor}.
|
||||
* @return
|
||||
*/
|
||||
public Floor floor() {
|
||||
return usesFieldRef() ? Floor.floorValueOf(fieldReference) : Floor.floorValueOf(expression);
|
||||
@@ -212,7 +212,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that calculates the natural logarithm ln (i.e loge) of the assoicated
|
||||
* number.
|
||||
*
|
||||
* @return new instance of {@link Ln}.
|
||||
* @return
|
||||
*/
|
||||
public Ln ln() {
|
||||
return usesFieldRef() ? Ln.lnValueOf(fieldReference) : Ln.lnValueOf(expression);
|
||||
@@ -223,7 +223,7 @@ public class ArithmeticOperators {
|
||||
* referenced via {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
* @return
|
||||
*/
|
||||
public Log log(String fieldReference) {
|
||||
|
||||
@@ -236,7 +236,7 @@ public class ArithmeticOperators {
|
||||
* extracted by given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
* @return
|
||||
*/
|
||||
public Log log(AggregationExpression expression) {
|
||||
|
||||
@@ -249,7 +249,7 @@ public class ArithmeticOperators {
|
||||
* {@literal base}.
|
||||
*
|
||||
* @param base must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
* @return
|
||||
*/
|
||||
public Log log(Number base) {
|
||||
|
||||
@@ -264,7 +264,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that calculates the log base 10 for the associated number.
|
||||
*
|
||||
* @return new instance of {@link Log10}.
|
||||
* @return
|
||||
*/
|
||||
public Log10 log10() {
|
||||
return usesFieldRef() ? Log10.log10ValueOf(fieldReference) : Log10.log10ValueOf(expression);
|
||||
@@ -275,7 +275,7 @@ public class ArithmeticOperators {
|
||||
* remainder.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
* @return
|
||||
*/
|
||||
public Mod mod(String fieldReference) {
|
||||
|
||||
@@ -288,7 +288,7 @@ public class ArithmeticOperators {
|
||||
* remainder.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
* @return
|
||||
*/
|
||||
public Mod mod(AggregationExpression expression) {
|
||||
|
||||
@@ -301,7 +301,7 @@ public class ArithmeticOperators {
|
||||
* remainder.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
* @return
|
||||
*/
|
||||
public Mod mod(Number value) {
|
||||
|
||||
@@ -317,7 +317,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that multiplies the associated number with another.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
* @return
|
||||
*/
|
||||
public Multiply multiplyBy(String fieldReference) {
|
||||
|
||||
@@ -329,7 +329,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that multiplies the associated number with another.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
* @return
|
||||
*/
|
||||
public Multiply multiplyBy(AggregationExpression expression) {
|
||||
|
||||
@@ -341,7 +341,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that multiplies the associated number with another.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
* @return
|
||||
*/
|
||||
public Multiply multiplyBy(Number value) {
|
||||
|
||||
@@ -357,7 +357,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that raises the associated number to the specified exponent.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
* @return
|
||||
*/
|
||||
public Pow pow(String fieldReference) {
|
||||
|
||||
@@ -369,7 +369,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that raises the associated number to the specified exponent.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
* @return
|
||||
*/
|
||||
public Pow pow(AggregationExpression expression) {
|
||||
|
||||
@@ -381,7 +381,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that raises the associated number to the specified exponent.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
* @return
|
||||
*/
|
||||
public Pow pow(Number value) {
|
||||
|
||||
@@ -396,7 +396,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that calculates the square root of the associated number.
|
||||
*
|
||||
* @return new instance of {@link Sqrt}.
|
||||
* @return
|
||||
*/
|
||||
public Sqrt sqrt() {
|
||||
return usesFieldRef() ? Sqrt.sqrtOf(fieldReference) : Sqrt.sqrtOf(expression);
|
||||
@@ -406,7 +406,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that subtracts value of given from the associated number.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Subtract}.
|
||||
* @return
|
||||
*/
|
||||
public Subtract subtract(String fieldReference) {
|
||||
|
||||
@@ -418,7 +418,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link AggregationExpression} that subtracts value of given from the associated number.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Subtract}.
|
||||
* @return
|
||||
*/
|
||||
public Subtract subtract(AggregationExpression expression) {
|
||||
|
||||
@@ -429,8 +429,8 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that subtracts value from the associated number.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Subtract}.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public Subtract subtract(Number value) {
|
||||
|
||||
@@ -445,7 +445,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that truncates a number to its integer.
|
||||
*
|
||||
* @return new instance of {@link Trunc}.
|
||||
* @return
|
||||
*/
|
||||
public Trunc trunc() {
|
||||
return usesFieldRef() ? Trunc.truncValueOf(fieldReference) : Trunc.truncValueOf(expression);
|
||||
@@ -454,7 +454,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that calculates and returns the sum of numeric values.
|
||||
*
|
||||
* @return new instance of {@link Sum}.
|
||||
* @return
|
||||
*/
|
||||
public Sum sum() {
|
||||
return usesFieldRef() ? AccumulatorOperators.Sum.sumOf(fieldReference)
|
||||
@@ -464,7 +464,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that returns the average value of the numeric values.
|
||||
*
|
||||
* @return new instance of {@link Avg}.
|
||||
* @return
|
||||
*/
|
||||
public Avg avg() {
|
||||
return usesFieldRef() ? AccumulatorOperators.Avg.avgOf(fieldReference)
|
||||
@@ -474,7 +474,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that returns the maximum value.
|
||||
*
|
||||
* @return new instance of {@link Max}.
|
||||
* @return
|
||||
*/
|
||||
public Max max() {
|
||||
return usesFieldRef() ? AccumulatorOperators.Max.maxOf(fieldReference)
|
||||
@@ -484,7 +484,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that returns the minimum value.
|
||||
*
|
||||
* @return new instance of {@link Min}.
|
||||
* @return
|
||||
*/
|
||||
public Min min() {
|
||||
return usesFieldRef() ? AccumulatorOperators.Min.minOf(fieldReference)
|
||||
@@ -494,7 +494,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that calculates the population standard deviation of the input values.
|
||||
*
|
||||
* @return new instance of {@link StdDevPop}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevPop stdDevPop() {
|
||||
return usesFieldRef() ? AccumulatorOperators.StdDevPop.stdDevPopOf(fieldReference)
|
||||
@@ -504,7 +504,7 @@ public class ArithmeticOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that calculates the sample standard deviation of the input values.
|
||||
*
|
||||
* @return new instance of {@link StdDevSamp}.
|
||||
* @return
|
||||
*/
|
||||
public StdDevSamp stdDevSamp() {
|
||||
return usesFieldRef() ? AccumulatorOperators.StdDevSamp.stdDevSampOf(fieldReference)
|
||||
@@ -536,7 +536,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Abs}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Abs}.
|
||||
* @return
|
||||
*/
|
||||
public static Abs absoluteValueOf(String fieldReference) {
|
||||
|
||||
@@ -548,7 +548,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Abs}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Abs}.
|
||||
* @return
|
||||
*/
|
||||
public static Abs absoluteValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -560,7 +560,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Abs}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Abs}.
|
||||
* @return
|
||||
*/
|
||||
public static Abs absoluteValueOf(Number value) {
|
||||
|
||||
@@ -589,7 +589,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Add}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
* @return
|
||||
*/
|
||||
public static Add valueOf(String fieldReference) {
|
||||
|
||||
@@ -601,7 +601,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Add}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
* @return
|
||||
*/
|
||||
public static Add valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -613,7 +613,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Add}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
* @return
|
||||
*/
|
||||
public static Add valueOf(Number value) {
|
||||
|
||||
@@ -621,36 +621,18 @@ public class ArithmeticOperators {
|
||||
return new Add(Collections.singletonList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the value stored at the given field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
*/
|
||||
public Add add(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Add(append(Fields.field(fieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the evaluation result of the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
*/
|
||||
public Add add(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Add(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Add}.
|
||||
*/
|
||||
public Add add(Number value) {
|
||||
return new Add(append(value));
|
||||
}
|
||||
@@ -676,7 +658,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Ceil}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Ceil}.
|
||||
* @return
|
||||
*/
|
||||
public static Ceil ceilValueOf(String fieldReference) {
|
||||
|
||||
@@ -688,7 +670,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Ceil}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Ceil}.
|
||||
* @return
|
||||
*/
|
||||
public static Ceil ceilValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -700,7 +682,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Ceil}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Ceil}.
|
||||
* @return
|
||||
*/
|
||||
public static Ceil ceilValueOf(Number value) {
|
||||
|
||||
@@ -729,7 +711,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Divide}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
* @return
|
||||
*/
|
||||
public static Divide valueOf(String fieldReference) {
|
||||
|
||||
@@ -741,7 +723,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Divide}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
* @return
|
||||
*/
|
||||
public static Divide valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -753,7 +735,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Divide}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
* @return
|
||||
*/
|
||||
public static Divide valueOf(Number value) {
|
||||
|
||||
@@ -761,36 +743,18 @@ public class ArithmeticOperators {
|
||||
return new Divide(Collections.singletonList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide by the value stored at the given field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
*/
|
||||
public Divide divideBy(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Divide(append(Fields.field(fieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide by the evaluation results of the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
*/
|
||||
public Divide divideBy(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Divide(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide by the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Divide}.
|
||||
*/
|
||||
public Divide divideBy(Number value) {
|
||||
return new Divide(append(value));
|
||||
}
|
||||
@@ -816,7 +780,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Exp}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Exp}.
|
||||
* @return
|
||||
*/
|
||||
public static Exp expValueOf(String fieldReference) {
|
||||
|
||||
@@ -828,7 +792,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Exp}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Exp}.
|
||||
* @return
|
||||
*/
|
||||
public static Exp expValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -840,7 +804,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Exp}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Exp}.
|
||||
* @return
|
||||
*/
|
||||
public static Exp expValueOf(Number value) {
|
||||
|
||||
@@ -869,7 +833,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Floor}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Floor}.
|
||||
* @return
|
||||
*/
|
||||
public static Floor floorValueOf(String fieldReference) {
|
||||
|
||||
@@ -881,7 +845,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Floor}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Floor}.
|
||||
* @return
|
||||
*/
|
||||
public static Floor floorValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -893,7 +857,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Floor}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Floor}.
|
||||
* @return
|
||||
*/
|
||||
public static Floor floorValueOf(Number value) {
|
||||
|
||||
@@ -922,7 +886,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Ln}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Ln}.
|
||||
* @return
|
||||
*/
|
||||
public static Ln lnValueOf(String fieldReference) {
|
||||
|
||||
@@ -934,7 +898,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Ln}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Ln}.
|
||||
* @return
|
||||
*/
|
||||
public static Ln lnValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -946,7 +910,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Ln}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Ln}.
|
||||
* @return
|
||||
*/
|
||||
public static Ln lnValueOf(Number value) {
|
||||
|
||||
@@ -975,7 +939,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Min}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
* @return
|
||||
*/
|
||||
public static Log valueOf(String fieldReference) {
|
||||
|
||||
@@ -987,7 +951,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Log}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
* @return
|
||||
*/
|
||||
public static Log valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1007,36 +971,18 @@ public class ArithmeticOperators {
|
||||
return new Log(Collections.singletonList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the value stored at the given field as log base.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
*/
|
||||
public Log log(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Log(append(Fields.field(fieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the evaluated value of the given {@link AggregationExpression} as log base.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
*/
|
||||
public Log log(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Log(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the given value as log base.
|
||||
*
|
||||
* @param base must not be {@literal null}.
|
||||
* @return new instance of {@link Log}.
|
||||
*/
|
||||
public Log log(Number base) {
|
||||
return new Log(append(base));
|
||||
}
|
||||
@@ -1062,7 +1008,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Log10}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Log10}.
|
||||
* @return
|
||||
*/
|
||||
public static Log10 log10ValueOf(String fieldReference) {
|
||||
|
||||
@@ -1074,7 +1020,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Log10}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Log10}.
|
||||
* @return
|
||||
*/
|
||||
public static Log10 log10ValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1086,7 +1032,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Log10}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Log10}.
|
||||
* @return
|
||||
*/
|
||||
public static Log10 log10ValueOf(Number value) {
|
||||
|
||||
@@ -1115,7 +1061,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Mod}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
* @return
|
||||
*/
|
||||
public static Mod valueOf(String fieldReference) {
|
||||
|
||||
@@ -1127,7 +1073,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Mod}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
* @return
|
||||
*/
|
||||
public static Mod valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1139,7 +1085,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Mod}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
* @return
|
||||
*/
|
||||
public static Mod valueOf(Number value) {
|
||||
|
||||
@@ -1147,36 +1093,18 @@ public class ArithmeticOperators {
|
||||
return new Mod(Collections.singletonList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the value stored at the given field as mod base.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
*/
|
||||
public Mod mod(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Mod(append(Fields.field(fieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use evaluated value of the given {@link AggregationExpression} as mod base.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
*/
|
||||
public Mod mod(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Mod(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the given value as mod base.
|
||||
*
|
||||
* @param base must not be {@literal null}.
|
||||
* @return new instance of {@link Mod}.
|
||||
*/
|
||||
public Mod mod(Number base) {
|
||||
return new Mod(append(base));
|
||||
}
|
||||
@@ -1202,7 +1130,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Multiply}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
* @return
|
||||
*/
|
||||
public static Multiply valueOf(String fieldReference) {
|
||||
|
||||
@@ -1214,7 +1142,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Multiply}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
* @return
|
||||
*/
|
||||
public static Multiply valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1226,7 +1154,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Multiply}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
* @return
|
||||
*/
|
||||
public static Multiply valueOf(Number value) {
|
||||
|
||||
@@ -1234,36 +1162,18 @@ public class ArithmeticOperators {
|
||||
return new Multiply(Collections.singletonList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply by the value stored at the given field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
*/
|
||||
public Multiply multiplyBy(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Multiply(append(Fields.field(fieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply by the evaluated value of the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
*/
|
||||
public Multiply multiplyBy(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Multiply(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply by the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Multiply}.
|
||||
*/
|
||||
public Multiply multiplyBy(Number value) {
|
||||
return new Multiply(append(value));
|
||||
}
|
||||
@@ -1321,36 +1231,18 @@ public class ArithmeticOperators {
|
||||
return new Pow(Collections.singletonList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pow by the value stored at the given field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
*/
|
||||
public Pow pow(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Pow(append(Fields.field(fieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pow by the evaluated value of the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
*/
|
||||
public Pow pow(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Pow(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pow by the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
*/
|
||||
public Pow pow(Number value) {
|
||||
return new Pow(append(value));
|
||||
}
|
||||
@@ -1376,7 +1268,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Sqrt}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Sqrt}.
|
||||
* @return
|
||||
*/
|
||||
public static Sqrt sqrtOf(String fieldReference) {
|
||||
|
||||
@@ -1388,7 +1280,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Sqrt}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Sqrt}.
|
||||
* @return
|
||||
*/
|
||||
public static Sqrt sqrtOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1400,7 +1292,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Sqrt}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Sqrt}.
|
||||
* @return
|
||||
*/
|
||||
public static Sqrt sqrtOf(Number value) {
|
||||
|
||||
@@ -1429,7 +1321,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Subtract}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Subtract}.
|
||||
* @return
|
||||
*/
|
||||
public static Subtract valueOf(String fieldReference) {
|
||||
|
||||
@@ -1441,7 +1333,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Subtract}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Subtract}.
|
||||
* @return
|
||||
*/
|
||||
public static Subtract valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1453,7 +1345,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Subtract}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Subtract}.
|
||||
* @return
|
||||
*/
|
||||
public static Subtract valueOf(Number value) {
|
||||
|
||||
@@ -1461,36 +1353,18 @@ public class ArithmeticOperators {
|
||||
return new Subtract(Collections.singletonList(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract the value stored at the given field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
*/
|
||||
public Subtract subtract(String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
return new Subtract(append(Fields.field(fieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract the evaluated value of the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
*/
|
||||
public Subtract subtract(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Subtract(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Pow}.
|
||||
*/
|
||||
public Subtract subtract(Number value) {
|
||||
return new Subtract(append(value));
|
||||
}
|
||||
@@ -1516,7 +1390,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Trunc}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Trunc}.
|
||||
* @return
|
||||
*/
|
||||
public static Trunc truncValueOf(String fieldReference) {
|
||||
|
||||
@@ -1528,7 +1402,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Trunc}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Trunc}.
|
||||
* @return
|
||||
*/
|
||||
public static Trunc truncValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1540,7 +1414,7 @@ public class ArithmeticOperators {
|
||||
* Creates new {@link Trunc}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Trunc}.
|
||||
* @return
|
||||
*/
|
||||
public static Trunc truncValueOf(Number value) {
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,7 +33,6 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Shashank Sharma
|
||||
* @since 1.0
|
||||
*/
|
||||
public class ArrayOperators {
|
||||
@@ -43,7 +41,7 @@ public class ArrayOperators {
|
||||
* Take the array referenced by given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ArrayOperatorFactory arrayOf(String fieldReference) {
|
||||
return new ArrayOperatorFactory(fieldReference);
|
||||
@@ -53,31 +51,19 @@ public class ArrayOperators {
|
||||
* Take the array referenced resulting from the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ArrayOperatorFactory arrayOf(AggregationExpression expression) {
|
||||
return new ArrayOperatorFactory(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the given {@link Collection values} {@link AggregationExpression}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayOperatorFactory}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static ArrayOperatorFactory arrayOf(Collection<?> values) {
|
||||
return new ArrayOperatorFactory(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public static class ArrayOperatorFactory {
|
||||
|
||||
private final @Nullable String fieldReference;
|
||||
private final @Nullable AggregationExpression expression;
|
||||
private final @Nullable Collection values;
|
||||
private final String fieldReference;
|
||||
private final AggregationExpression expression;
|
||||
|
||||
/**
|
||||
* Creates new {@link ArrayOperatorFactory} for given {@literal fieldReference}.
|
||||
@@ -89,7 +75,6 @@ public class ArrayOperators {
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
this.fieldReference = fieldReference;
|
||||
this.expression = null;
|
||||
this.values = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,29 +87,14 @@ public class ArrayOperators {
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
this.fieldReference = null;
|
||||
this.expression = expression;
|
||||
this.values = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link ArrayOperatorFactory} for given values.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public ArrayOperatorFactory(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
this.fieldReference = null;
|
||||
this.expression = null;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that takes the associated array and returns the element at the
|
||||
* specified array {@literal position}.
|
||||
*
|
||||
* @param position the element index.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
public ArrayElemAt elementAt(int position) {
|
||||
return createArrayElemAt().elementAt(position);
|
||||
@@ -135,7 +105,7 @@ public class ArrayOperators {
|
||||
* resulting form the given {@literal expression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
* @return
|
||||
*/
|
||||
public ArrayElemAt elementAt(AggregationExpression expression) {
|
||||
|
||||
@@ -148,7 +118,7 @@ public class ArrayOperators {
|
||||
* defined by the referenced {@literal field}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
* @return
|
||||
*/
|
||||
public ArrayElemAt elementAt(String fieldReference) {
|
||||
|
||||
@@ -157,12 +127,7 @@ public class ArrayOperators {
|
||||
}
|
||||
|
||||
private ArrayElemAt createArrayElemAt() {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return ArrayElemAt.arrayOf(fieldReference);
|
||||
}
|
||||
|
||||
return usesExpression() ? ArrayElemAt.arrayOf(expression) : ArrayElemAt.arrayOf(values);
|
||||
return usesFieldRef() ? ArrayElemAt.arrayOf(fieldReference) : ArrayElemAt.arrayOf(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +135,7 @@ public class ArrayOperators {
|
||||
* {@literal arrayFieldReference} to it.
|
||||
*
|
||||
* @param arrayFieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ConcatArrays}.
|
||||
* @return
|
||||
*/
|
||||
public ConcatArrays concat(String arrayFieldReference) {
|
||||
|
||||
@@ -183,7 +148,7 @@ public class ArrayOperators {
|
||||
* the given {@literal expression} to it.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ConcatArrays}.
|
||||
* @return
|
||||
*/
|
||||
public ConcatArrays concat(AggregationExpression expression) {
|
||||
|
||||
@@ -192,68 +157,44 @@ public class ArrayOperators {
|
||||
}
|
||||
|
||||
private ConcatArrays createConcatArrays() {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return ConcatArrays.arrayOf(fieldReference);
|
||||
}
|
||||
|
||||
return usesExpression() ? ConcatArrays.arrayOf(expression) : ConcatArrays.arrayOf(values);
|
||||
return usesFieldRef() ? ConcatArrays.arrayOf(fieldReference) : ConcatArrays.arrayOf(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that takes the associated array and selects a subset of the array to
|
||||
* return based on the specified condition.
|
||||
*
|
||||
* @return new instance of {@link AsBuilder} to create a {@link Filter}.
|
||||
* @return
|
||||
*/
|
||||
public AsBuilder filter() {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return Filter.filter(fieldReference);
|
||||
}
|
||||
|
||||
Assert.state(values != null, "Values must not be null!");
|
||||
return Filter.filter(new ArrayList<>(values));
|
||||
return Filter.filter(fieldReference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that takes the associated array and an check if its an array.
|
||||
*
|
||||
* @return new instance of {@link IsArray}.
|
||||
* @return
|
||||
*/
|
||||
public IsArray isArray() {
|
||||
|
||||
Assert.state(values == null, "Does it make sense to call isArray on an array? Maybe just skip it?");
|
||||
|
||||
return usesFieldRef() ? IsArray.isArray(fieldReference) : IsArray.isArray(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that takes the associated array and retrieves its length.
|
||||
*
|
||||
* @return new instance of {@link Size}.
|
||||
* @return
|
||||
*/
|
||||
public Size length() {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return Size.lengthOfArray(fieldReference);
|
||||
}
|
||||
|
||||
return usesExpression() ? Size.lengthOfArray(expression) : Size.lengthOfArray(values);
|
||||
return usesFieldRef() ? Size.lengthOfArray(fieldReference) : Size.lengthOfArray(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that takes the associated array and selects a subset from it.
|
||||
*
|
||||
* @return new instance of {@link Slice}.
|
||||
* @return
|
||||
*/
|
||||
public Slice slice() {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return Slice.sliceArrayOf(fieldReference);
|
||||
}
|
||||
|
||||
return usesExpression() ? Slice.sliceArrayOf(expression) : Slice.sliceArrayOf(values);
|
||||
return usesFieldRef() ? Slice.sliceArrayOf(fieldReference) : Slice.sliceArrayOf(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,31 +202,20 @@ public class ArrayOperators {
|
||||
* value and returns the array index (zero-based) of the first occurrence.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link IndexOfArray}.
|
||||
* @return
|
||||
*/
|
||||
public IndexOfArray indexOf(Object value) {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return IndexOfArray.arrayOf(fieldReference).indexOf(value);
|
||||
}
|
||||
|
||||
return usesExpression() ? IndexOfArray.arrayOf(expression).indexOf(value)
|
||||
: IndexOfArray.arrayOf(values).indexOf(value);
|
||||
return usesFieldRef() ? IndexOfArray.arrayOf(fieldReference).indexOf(value)
|
||||
: IndexOfArray.arrayOf(expression).indexOf(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that returns an array with the elements in reverse order.
|
||||
*
|
||||
* @return new instance of {@link ReverseArray}.
|
||||
* @return
|
||||
*/
|
||||
public ReverseArray reverse() {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return ReverseArray.reverseArrayOf(fieldReference);
|
||||
}
|
||||
|
||||
return usesExpression() ? ReverseArray.reverseArrayOf(expression)
|
||||
: ReverseArray.reverseArrayOf(Collections.singletonList(values));
|
||||
return usesFieldRef() ? ReverseArray.reverseArrayOf(fieldReference) : ReverseArray.reverseArrayOf(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,7 +223,7 @@ public class ArrayOperators {
|
||||
* an array and combines them into a single value.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ReduceInitialValueBuilder} to create {@link Reduce}.
|
||||
* @return
|
||||
*/
|
||||
public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(AggregationExpression expression) {
|
||||
|
||||
@@ -305,8 +235,8 @@ public class ArrayOperators {
|
||||
* Start creating new {@link AggregationExpression} that applies an {@link AggregationExpression} to each element in
|
||||
* an array and combines them into a single value.
|
||||
*
|
||||
* @param expressions must not be {@literal null}.
|
||||
* @return new instance of {@link ReduceInitialValueBuilder} to create {@link Reduce}.
|
||||
* @param expressions
|
||||
* @return
|
||||
*/
|
||||
public ArrayOperatorFactory.ReduceInitialValueBuilder reduce(PropertyExpression... expressions) {
|
||||
|
||||
@@ -320,15 +250,10 @@ public class ArrayOperators {
|
||||
* the second input array, etc.
|
||||
*
|
||||
* @param arrays must not be {@literal null}.
|
||||
* @return new instance of {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public Zip zipWith(Object... arrays) {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return Zip.arrayOf(fieldReference).zip(arrays);
|
||||
}
|
||||
|
||||
return (usesExpression() ? Zip.arrayOf(expression) : Zip.arrayOf(values)).zip(arrays);
|
||||
return (usesFieldRef() ? Zip.arrayOf(fieldReference) : Zip.arrayOf(expression)).zip(arrays);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,15 +261,10 @@ public class ArrayOperators {
|
||||
* associated array.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link In}.
|
||||
* @return
|
||||
*/
|
||||
public In containsValue(Object value) {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return In.arrayOf(fieldReference).containsValue(value);
|
||||
}
|
||||
|
||||
return (usesExpression() ? In.arrayOf(expression) : In.arrayOf(values)).containsValue(value);
|
||||
return (usesFieldRef() ? In.arrayOf(fieldReference) : In.arrayOf(expression)).containsValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,11 +276,8 @@ public class ArrayOperators {
|
||||
*/
|
||||
public ArrayToObject toObject() {
|
||||
|
||||
if (usesFieldRef()) {
|
||||
return ArrayToObject.arrayValueOfToObject(fieldReference);
|
||||
}
|
||||
|
||||
return usesExpression() ? ArrayToObject.arrayValueOfToObject(expression) : ArrayToObject.arrayToObject(values);
|
||||
return usesFieldRef() ? ArrayToObject.arrayValueOfToObject(fieldReference)
|
||||
: ArrayToObject.arrayValueOfToObject(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,20 +294,9 @@ public class ArrayOperators {
|
||||
Reduce startingWith(Object initialValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if {@link #fieldReference} is not {@literal null}.
|
||||
*/
|
||||
private boolean usesFieldRef() {
|
||||
return fieldReference != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if {@link #expression} is not {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
private boolean usesExpression() {
|
||||
return expression != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,7 +319,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link ArrayElemAt}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
* @return
|
||||
*/
|
||||
public static ArrayElemAt arrayOf(String fieldReference) {
|
||||
|
||||
@@ -425,7 +331,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link ArrayElemAt}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
* @return
|
||||
*/
|
||||
public static ArrayElemAt arrayOf(AggregationExpression expression) {
|
||||
|
||||
@@ -433,47 +339,16 @@ public class ArrayOperators {
|
||||
return new ArrayElemAt(Collections.singletonList(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link ArrayElemAt}.
|
||||
*
|
||||
* @param values The array members. Must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static ArrayElemAt arrayOf(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
return new ArrayElemAt(Collections.singletonList(values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the element with given index number.
|
||||
*
|
||||
* @param index the index number
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
*/
|
||||
public ArrayElemAt elementAt(int index) {
|
||||
return new ArrayElemAt(append(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the element at the index number evaluated from the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
*/
|
||||
public ArrayElemAt elementAt(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new ArrayElemAt(append(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the element at the index number traken from the given field.
|
||||
*
|
||||
* @param arrayFieldReference the field name.
|
||||
* @return new instance of {@link ArrayElemAt}.
|
||||
*/
|
||||
public ArrayElemAt elementAt(String arrayFieldReference) {
|
||||
|
||||
Assert.notNull(arrayFieldReference, "ArrayReference must not be null!");
|
||||
@@ -501,7 +376,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link ConcatArrays}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ConcatArrays}.
|
||||
* @return
|
||||
*/
|
||||
public static ConcatArrays arrayOf(String fieldReference) {
|
||||
|
||||
@@ -513,7 +388,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link ConcatArrays}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ConcatArrays}.
|
||||
* @return
|
||||
*/
|
||||
public static ConcatArrays arrayOf(AggregationExpression expression) {
|
||||
|
||||
@@ -521,37 +396,12 @@ public class ArrayOperators {
|
||||
return new ConcatArrays(Collections.singletonList(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link ConcatArrays}.
|
||||
*
|
||||
* @param values The array members. Must not be {@literal null}.
|
||||
* @return new instance of {@link ConcatArrays}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static ConcatArrays arrayOf(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
return new ConcatArrays(Collections.singletonList(values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat with the array stored at the given field.
|
||||
*
|
||||
* @param arrayFieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ConcatArrays}.
|
||||
*/
|
||||
public ConcatArrays concat(String arrayFieldReference) {
|
||||
|
||||
Assert.notNull(arrayFieldReference, "ArrayFieldReference must not be null!");
|
||||
return new ConcatArrays(append(Fields.field(arrayFieldReference)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat with the array resulting from the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ConcatArrays}.
|
||||
*/
|
||||
public ConcatArrays concat(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
@@ -604,7 +454,7 @@ public class ArrayOperators {
|
||||
* Set the {@literal values} to apply the {@code $filter} to.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link AsBuilder} to create the {@link Filter}.
|
||||
* @return
|
||||
*/
|
||||
public static AsBuilder filter(List<?> values) {
|
||||
|
||||
@@ -681,7 +531,7 @@ public class ArrayOperators {
|
||||
* Set the {@literal variableName} for the elements in the input array.
|
||||
*
|
||||
* @param variableName must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
ConditionBuilder as(String variableName);
|
||||
}
|
||||
@@ -695,7 +545,7 @@ public class ArrayOperators {
|
||||
* Set the {@link AggregationExpression} that determines whether to include the element in the resulting array.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Filter by(AggregationExpression expression);
|
||||
|
||||
@@ -703,7 +553,7 @@ public class ArrayOperators {
|
||||
* Set the {@literal expression} that determines whether to include the element in the resulting array.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Filter by(String expression);
|
||||
|
||||
@@ -711,7 +561,7 @@ public class ArrayOperators {
|
||||
* Set the {@literal expression} that determines whether to include the element in the resulting array.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
Filter by(Document expression);
|
||||
}
|
||||
@@ -730,7 +580,7 @@ public class ArrayOperators {
|
||||
/**
|
||||
* Creates new {@link InputBuilder}.
|
||||
*
|
||||
* @return new instance of {@link FilterExpressionBuilder}.
|
||||
* @return
|
||||
*/
|
||||
public static InputBuilder newBuilder() {
|
||||
return new FilterExpressionBuilder();
|
||||
@@ -830,7 +680,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link IsArray}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link IsArray}.
|
||||
* @return
|
||||
*/
|
||||
public static IsArray isArray(String fieldReference) {
|
||||
|
||||
@@ -842,7 +692,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link IsArray}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link IsArray}.
|
||||
* @return
|
||||
*/
|
||||
public static IsArray isArray(AggregationExpression expression) {
|
||||
|
||||
@@ -871,7 +721,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link Size}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Size}.
|
||||
* @return
|
||||
*/
|
||||
public static Size lengthOfArray(String fieldReference) {
|
||||
|
||||
@@ -883,26 +733,13 @@ public class ArrayOperators {
|
||||
* Creates new {@link Size}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Size}.
|
||||
* @return
|
||||
*/
|
||||
public static Size lengthOfArray(AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
return new Size(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link Size}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link Size}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static Size lengthOfArray(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
return new Size(Collections.singletonList(values));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -925,7 +762,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link Slice}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Slice}.
|
||||
* @return
|
||||
*/
|
||||
public static Slice sliceArrayOf(String fieldReference) {
|
||||
|
||||
@@ -937,7 +774,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link Slice}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Slice}.
|
||||
* @return
|
||||
*/
|
||||
public static Slice sliceArrayOf(AggregationExpression expression) {
|
||||
|
||||
@@ -945,35 +782,10 @@ public class ArrayOperators {
|
||||
return new Slice(Collections.singletonList(expression));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link Slice}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link Slice}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static Slice sliceArrayOf(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
return new Slice(Collections.singletonList(values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Slice the number of elements.
|
||||
*
|
||||
* @param nrElements elements to slice.
|
||||
* @return new instance of {@link Slice}.
|
||||
*/
|
||||
public Slice itemCount(int nrElements) {
|
||||
return new Slice(append(nrElements));
|
||||
}
|
||||
|
||||
/**
|
||||
* Slice using offset and count.
|
||||
*
|
||||
* @param position the start position
|
||||
* @return new instance of {@link SliceElementsBuilder} to create {@link Slice}.
|
||||
*/
|
||||
public SliceElementsBuilder offset(final int position) {
|
||||
|
||||
return new SliceElementsBuilder() {
|
||||
@@ -1020,7 +832,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link IndexOfArray}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link IndexOfArray}.
|
||||
* @return
|
||||
*/
|
||||
public static IndexOfArrayBuilder arrayOf(String fieldReference) {
|
||||
|
||||
@@ -1032,7 +844,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link IndexOfArray}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link IndexOfArray}.
|
||||
* @return
|
||||
*/
|
||||
public static IndexOfArrayBuilder arrayOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1040,25 +852,6 @@ public class ArrayOperators {
|
||||
return new IndexOfArrayBuilder(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start creating new {@link IndexOfArray}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link IndexOfArrayBuilder} to create {@link IndexOfArray}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static IndexOfArrayBuilder arrayOf(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
return new IndexOfArrayBuilder(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup within a given range.
|
||||
*
|
||||
* @param range the lookup range.
|
||||
* @return new instance of {@link IndexOfArray}.
|
||||
*/
|
||||
public IndexOfArray within(Range<Long> range) {
|
||||
return new IndexOfArray(append(AggregationUtils.toRangeValues(range)));
|
||||
}
|
||||
@@ -1078,7 +871,7 @@ public class ArrayOperators {
|
||||
* Set the {@literal value} to check for its index in the array.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link IndexOfArray}.
|
||||
* @return
|
||||
*/
|
||||
public IndexOfArray indexOf(Object value) {
|
||||
|
||||
@@ -1108,7 +901,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link RangeOperator}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link RangeOperatorBuilder} to create {@link RangeOperator}.
|
||||
* @return
|
||||
*/
|
||||
public static RangeOperatorBuilder rangeStartingAt(String fieldReference) {
|
||||
return new RangeOperatorBuilder(Fields.field(fieldReference));
|
||||
@@ -1118,7 +911,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link RangeOperator}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link RangeOperatorBuilder} to create {@link RangeOperator}.
|
||||
* @return
|
||||
*/
|
||||
public static RangeOperatorBuilder rangeStartingAt(AggregationExpression expression) {
|
||||
return new RangeOperatorBuilder(expression);
|
||||
@@ -1128,7 +921,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link RangeOperator}.
|
||||
*
|
||||
* @param value
|
||||
* @return new instance of {@link RangeOperator}.
|
||||
* @return
|
||||
*/
|
||||
public static RangeOperatorBuilder rangeStartingAt(long value) {
|
||||
return new RangeOperatorBuilder(value);
|
||||
@@ -1150,7 +943,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link RangeOperator}.
|
||||
*
|
||||
* @param index
|
||||
* @return new instance of {@link RangeOperator}.
|
||||
* @return
|
||||
*/
|
||||
public RangeOperator to(long index) {
|
||||
return new RangeOperator(Arrays.asList(startPoint, index));
|
||||
@@ -1160,7 +953,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link RangeOperator}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link RangeOperator}.
|
||||
* @return
|
||||
*/
|
||||
public RangeOperator to(AggregationExpression expression) {
|
||||
return new RangeOperator(Arrays.asList(startPoint, expression));
|
||||
@@ -1170,7 +963,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link RangeOperator}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link RangeOperator}.
|
||||
* @return
|
||||
*/
|
||||
public RangeOperator to(String fieldReference) {
|
||||
return new RangeOperator(Arrays.asList(startPoint, Fields.field(fieldReference)));
|
||||
@@ -1198,7 +991,7 @@ public class ArrayOperators {
|
||||
* Creates new {@link ReverseArray} given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ReverseArray}.
|
||||
* @return
|
||||
*/
|
||||
public static ReverseArray reverseArrayOf(String fieldReference) {
|
||||
return new ReverseArray(Fields.field(fieldReference));
|
||||
@@ -1208,22 +1001,11 @@ public class ArrayOperators {
|
||||
* Creates new {@link ReverseArray} given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ReverseArray}.
|
||||
* @return
|
||||
*/
|
||||
public static ReverseArray reverseArrayOf(AggregationExpression expression) {
|
||||
return new ReverseArray(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new {@link ReverseArray}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link ReverseArray}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static ReverseArray reverseArrayOf(Collection<?> values) {
|
||||
return new ReverseArray(values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1287,7 +1069,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link Reduce}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link InitialValueBuilder} to create {@link Reduce}.
|
||||
* @return
|
||||
*/
|
||||
public static InitialValueBuilder arrayOf(final String fieldReference) {
|
||||
|
||||
@@ -1326,7 +1108,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link Reduce}.
|
||||
*
|
||||
* @param arrayValueExpression must not be {@literal null}.
|
||||
* @return new instance of {@link InitialValueBuilder} to create {@link Reduce}.
|
||||
* @return
|
||||
*/
|
||||
public static InitialValueBuilder arrayOf(final AggregationExpression arrayValueExpression) {
|
||||
|
||||
@@ -1366,7 +1148,7 @@ public class ArrayOperators {
|
||||
* Define the initial cumulative value set before in is applied to the first element of the input array.
|
||||
*
|
||||
* @param initialValue must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
ReduceBuilder withInitialValue(Object initialValue);
|
||||
}
|
||||
@@ -1383,7 +1165,7 @@ public class ArrayOperators {
|
||||
* {@link Variable#VALUE} are available.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Reduce}.
|
||||
* @return
|
||||
*/
|
||||
Reduce reduce(AggregationExpression expression);
|
||||
|
||||
@@ -1394,7 +1176,7 @@ public class ArrayOperators {
|
||||
* {@link Variable#VALUE} are available.
|
||||
*
|
||||
* @param expressions must not be {@literal null}.
|
||||
* @return new instance of {@link Reduce}.
|
||||
* @return
|
||||
*/
|
||||
Reduce reduce(PropertyExpression... expressions);
|
||||
}
|
||||
@@ -1420,7 +1202,7 @@ public class ArrayOperators {
|
||||
* Define a result property for an {@link AggregationExpression} used in {@link Reduce}.
|
||||
*
|
||||
* @param name must not be {@literal null}.
|
||||
* @return new instance of {@link AsBuilder} to create {@link Reduce}.
|
||||
* @return
|
||||
*/
|
||||
public static AsBuilder property(final String name) {
|
||||
|
||||
@@ -1450,7 +1232,7 @@ public class ArrayOperators {
|
||||
* Set the {@link AggregationExpression} resulting in the properties value.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
PropertyExpression definedAs(AggregationExpression expression);
|
||||
}
|
||||
@@ -1507,7 +1289,7 @@ public class ArrayOperators {
|
||||
* eg. {@code $$value.product}
|
||||
*
|
||||
* @param property must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public Field referringTo(final String property) {
|
||||
|
||||
@@ -1556,7 +1338,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link Zip}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ZipBuilder} to create {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public static ZipBuilder arrayOf(String fieldReference) {
|
||||
|
||||
@@ -1568,7 +1350,7 @@ public class ArrayOperators {
|
||||
* Start creating new {@link Zip}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ZipBuilder} to create {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public static ZipBuilder arrayOf(AggregationExpression expression) {
|
||||
|
||||
@@ -1576,23 +1358,10 @@ public class ArrayOperators {
|
||||
return new ZipBuilder(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start creating new {@link Zip}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link Zip}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static ZipBuilder arrayOf(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Expression must not be null!");
|
||||
return new ZipBuilder(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link Zip} and set the {@code useLongestLength} property to {@literal true}.
|
||||
*
|
||||
* @return new instance of {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public Zip useLongestLength() {
|
||||
return new Zip(append("useLongestLength", true));
|
||||
@@ -1602,7 +1371,7 @@ public class ArrayOperators {
|
||||
* Optionally provide a default value.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public Zip defaultTo(String fieldReference) {
|
||||
|
||||
@@ -1614,7 +1383,7 @@ public class ArrayOperators {
|
||||
* Optionally provide a default value.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public Zip defaultTo(AggregationExpression expression) {
|
||||
|
||||
@@ -1626,7 +1395,7 @@ public class ArrayOperators {
|
||||
* Optionally provide a default value.
|
||||
*
|
||||
* @param array must not be {@literal null}.
|
||||
* @return new instance of {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public Zip defaultTo(Object[] array) {
|
||||
|
||||
@@ -1650,7 +1419,7 @@ public class ArrayOperators {
|
||||
* array, etc.
|
||||
*
|
||||
* @param arrays arrays to zip the referenced one with. must not be {@literal null}.
|
||||
* @return new instance of {@link Zip}.
|
||||
* @return
|
||||
*/
|
||||
public Zip zip(Object... arrays) {
|
||||
|
||||
@@ -1673,10 +1442,6 @@ public class ArrayOperators {
|
||||
* {@link AggregationExpression} for {@code $in}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Shashank Sharma
|
||||
* @see <a href=
|
||||
* "https://docs.mongodb.com/manual/reference/operator/aggregation/in/">https://docs.mongodb.com/manual/reference/operator/aggregation/in/</a>
|
||||
* @since 2.2
|
||||
*/
|
||||
public static class In extends AbstractAggregationExpression {
|
||||
|
||||
@@ -1693,16 +1458,20 @@ public class ArrayOperators {
|
||||
* Start creating {@link In}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link InBuilder} to create {@link In}.
|
||||
* @return
|
||||
*/
|
||||
public static InBuilder arrayOf(String fieldReference) {
|
||||
public static InBuilder arrayOf(final String fieldReference) {
|
||||
|
||||
Assert.notNull(fieldReference, "FieldReference must not be null!");
|
||||
|
||||
return value -> {
|
||||
return new InBuilder() {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return new In(Arrays.asList(value, Fields.field(fieldReference)));
|
||||
@Override
|
||||
public In containsValue(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return new In(Arrays.asList(value, Fields.field(fieldReference)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1710,36 +1479,20 @@ public class ArrayOperators {
|
||||
* Start creating {@link In}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link InBuilder} to create {@link In}.
|
||||
* @return
|
||||
*/
|
||||
public static InBuilder arrayOf(AggregationExpression expression) {
|
||||
public static InBuilder arrayOf(final AggregationExpression expression) {
|
||||
|
||||
Assert.notNull(expression, "Expression must not be null!");
|
||||
|
||||
return value -> {
|
||||
return new InBuilder() {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
@Override
|
||||
public In containsValue(Object value) {
|
||||
|
||||
return new In(Arrays.asList(value, expression));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for Aggregation In Search an Element in List of Objects to Filter Start creating {@link In}.
|
||||
*
|
||||
* @param values must not be {@literal null}.
|
||||
* @return new instance of {@link InBuilder}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public static InBuilder arrayOf(Collection<?> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
|
||||
return value -> {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return new In(Arrays.asList(value, values));
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return new In(Arrays.asList(value, expression));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1752,7 +1505,7 @@ public class ArrayOperators {
|
||||
* Set the {@literal value} to check for existence in the array.
|
||||
*
|
||||
* @param value must not be {@literal value}.
|
||||
* @return new instance of {@link In}.
|
||||
* @return
|
||||
*/
|
||||
In containsValue(Object value);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class BooleanOperators {
|
||||
* Take the array referenced by given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link BooleanOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static BooleanOperatorFactory valueOf(String fieldReference) {
|
||||
return new BooleanOperatorFactory(fieldReference);
|
||||
@@ -44,7 +44,7 @@ public class BooleanOperators {
|
||||
* Take the value resulting of the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link BooleanOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static BooleanOperatorFactory valueOf(AggregationExpression fieldReference) {
|
||||
return new BooleanOperatorFactory(fieldReference);
|
||||
@@ -55,7 +55,7 @@ public class BooleanOperators {
|
||||
* opposite boolean value.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Not}.
|
||||
* @return
|
||||
*/
|
||||
public static Not not(String fieldReference) {
|
||||
return Not.not(fieldReference);
|
||||
@@ -66,7 +66,7 @@ public class BooleanOperators {
|
||||
* and returns the opposite boolean value.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Not}.
|
||||
* @return
|
||||
*/
|
||||
public static Not not(AggregationExpression expression) {
|
||||
return Not.not(expression);
|
||||
@@ -109,7 +109,7 @@ public class BooleanOperators {
|
||||
* all of the expressions are {@literal true}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link And}.
|
||||
* @return
|
||||
*/
|
||||
public And and(AggregationExpression expression) {
|
||||
|
||||
@@ -122,7 +122,7 @@ public class BooleanOperators {
|
||||
* all of the expressions are {@literal true}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link And}.
|
||||
* @return
|
||||
*/
|
||||
public And and(String fieldReference) {
|
||||
|
||||
@@ -139,7 +139,7 @@ public class BooleanOperators {
|
||||
* any of the expressions are {@literal true}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Or}.
|
||||
* @return
|
||||
*/
|
||||
public Or or(AggregationExpression expression) {
|
||||
|
||||
@@ -152,7 +152,7 @@ public class BooleanOperators {
|
||||
* any of the expressions are {@literal true}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Or}.
|
||||
* @return
|
||||
*/
|
||||
public Or or(String fieldReference) {
|
||||
|
||||
@@ -167,7 +167,7 @@ public class BooleanOperators {
|
||||
/**
|
||||
* Creates new {@link AggregationExpression} that evaluates a boolean and returns the opposite boolean value.
|
||||
*
|
||||
* @return new instance of {@link Not}.
|
||||
* @return
|
||||
*/
|
||||
public Not not() {
|
||||
return usesFieldRef() ? Not.not(fieldReference) : Not.not(expression);
|
||||
@@ -198,8 +198,8 @@ public class BooleanOperators {
|
||||
* Creates new {@link And} that evaluates one or more expressions and returns {@literal true} if all of the
|
||||
* expressions are {@literal true}.
|
||||
*
|
||||
* @param expressions must not be {@literal null}.
|
||||
* @return new instance of {@link And}.
|
||||
* @param expressions
|
||||
* @return
|
||||
*/
|
||||
public static And and(Object... expressions) {
|
||||
return new And(Arrays.asList(expressions));
|
||||
@@ -209,7 +209,7 @@ public class BooleanOperators {
|
||||
* Creates new {@link And} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link And}.
|
||||
* @return
|
||||
*/
|
||||
public And andExpression(AggregationExpression expression) {
|
||||
|
||||
@@ -221,7 +221,7 @@ public class BooleanOperators {
|
||||
* Creates new {@link And} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link And}.
|
||||
* @return
|
||||
*/
|
||||
public And andField(String fieldReference) {
|
||||
|
||||
@@ -233,7 +233,7 @@ public class BooleanOperators {
|
||||
* Creates new {@link And} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link And}.
|
||||
* @return
|
||||
*/
|
||||
public And andValue(Object value) {
|
||||
|
||||
@@ -263,7 +263,7 @@ public class BooleanOperators {
|
||||
* expressions are {@literal true}.
|
||||
*
|
||||
* @param expressions must not be {@literal null}.
|
||||
* @return new instance of {@link Or}.
|
||||
* @return
|
||||
*/
|
||||
public static Or or(Object... expressions) {
|
||||
|
||||
@@ -275,7 +275,7 @@ public class BooleanOperators {
|
||||
* Creates new {@link Or} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Or}.
|
||||
* @return
|
||||
*/
|
||||
public Or orExpression(AggregationExpression expression) {
|
||||
|
||||
@@ -287,7 +287,7 @@ public class BooleanOperators {
|
||||
* Creates new {@link Or} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Or}.
|
||||
* @return
|
||||
*/
|
||||
public Or orField(String fieldReference) {
|
||||
|
||||
@@ -299,7 +299,7 @@ public class BooleanOperators {
|
||||
* Creates new {@link Or} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Or}.
|
||||
* @return
|
||||
*/
|
||||
public Or orValue(Object value) {
|
||||
|
||||
@@ -329,7 +329,7 @@ public class BooleanOperators {
|
||||
* value.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Not}.
|
||||
* @return
|
||||
*/
|
||||
public static Not not(String fieldReference) {
|
||||
|
||||
@@ -342,7 +342,7 @@ public class BooleanOperators {
|
||||
* returns the opposite boolean value.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Not}.
|
||||
* @return
|
||||
*/
|
||||
public static Not not(AggregationExpression expression) {
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core.aggregation;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.BucketAutoOperation.BucketAutoOperationOutputBuilder;
|
||||
import org.springframework.data.mongodb.core.aggregation.BucketOperationSupport.OutputBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* Encapsulates the aggregation framework {@code $bucketAuto}-operation. <br />
|
||||
* Bucket stage is typically used with {@link Aggregation} and {@code $facet}. Categorizes incoming documents into a
|
||||
@@ -113,7 +113,7 @@ public class BucketAutoOperation extends BucketOperationSupport<BucketAutoOperat
|
||||
* Configures a number of bucket {@literal buckets} and return a new {@link BucketAutoOperation}.
|
||||
*
|
||||
* @param buckets must be a positive number.
|
||||
* @return new instance of {@link BucketAutoOperation}.
|
||||
* @return
|
||||
*/
|
||||
public BucketAutoOperation withBuckets(int buckets) {
|
||||
|
||||
@@ -128,7 +128,7 @@ public class BucketAutoOperation extends BucketOperationSupport<BucketAutoOperat
|
||||
* Use either predefined {@link Granularities} or provide a own one.
|
||||
*
|
||||
* @param granularity must not be {@literal null}.
|
||||
* @return new instance of {@link BucketAutoOperation}.
|
||||
* @return
|
||||
*/
|
||||
public BucketAutoOperation withGranularity(Granularity granularity) {
|
||||
|
||||
@@ -209,7 +209,7 @@ public class BucketAutoOperation extends BucketOperationSupport<BucketAutoOperat
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @param operation must not be {@literal null}.
|
||||
* @param parameters must not be {@literal null}.
|
||||
* @param parameters
|
||||
*/
|
||||
protected ExpressionBucketAutoOperationBuilder(String expression, BucketAutoOperation operation,
|
||||
Object[] parameters) {
|
||||
|
||||
@@ -20,11 +20,11 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.data.mongodb.core.aggregation.BucketOperation.BucketOperationOutputBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* Encapsulates the aggregation framework {@code $bucket}-operation. <br />
|
||||
*
|
||||
@@ -110,7 +110,7 @@ public class BucketOperation extends BucketOperationSupport<BucketOperation, Buc
|
||||
* Configures a default bucket {@literal literal} and return a new {@link BucketOperation}.
|
||||
*
|
||||
* @param literal must not be {@literal null}.
|
||||
* @return new instance of {@link BucketOperation}.
|
||||
* @return
|
||||
*/
|
||||
public BucketOperation withDefaultBucket(Object literal) {
|
||||
|
||||
@@ -123,7 +123,7 @@ public class BucketOperation extends BucketOperationSupport<BucketOperation, Buc
|
||||
* preserved and the new {@literal boundaries} are appended.
|
||||
*
|
||||
* @param boundaries must not be {@literal null}.
|
||||
* @return new instance of {@link BucketOperation}.
|
||||
* @return
|
||||
*/
|
||||
public BucketOperation withBoundaries(Object... boundaries) {
|
||||
|
||||
@@ -204,12 +204,12 @@ public class BucketOperation extends BucketOperationSupport<BucketOperation, Buc
|
||||
extends ExpressionBucketOperationBuilderSupport<BucketOperationOutputBuilder, BucketOperation> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link ExpressionBucketOperationBuilderSupport} for the given value, {@link BucketOperation} and
|
||||
* parameters.
|
||||
* Creates a new {@link ExpressionBucketOperationBuilderSupport} for the given value, {@link BucketOperation}
|
||||
* and parameters.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @param operation must not be {@literal null}.
|
||||
* @param parameters must not be {@literal null}.
|
||||
* @param parameters
|
||||
*/
|
||||
protected ExpressionBucketOperationBuilder(String expression, BucketOperation operation, Object[] parameters) {
|
||||
super(expression, operation, parameters);
|
||||
|
||||
@@ -21,13 +21,14 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.springframework.data.mongodb.core.aggregation.BucketOperationSupport.OutputBuilder;
|
||||
import org.springframework.data.mongodb.core.aggregation.ExposedFields.ExposedField;
|
||||
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation.ProjectionOperationBuilder;
|
||||
import org.springframework.expression.spel.ast.Projection;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
/**
|
||||
* Base class for bucket operations that support output expressions the aggregation framework. <br />
|
||||
* Bucket stages collect documents into buckets and can contribute output fields. <br />
|
||||
@@ -103,7 +104,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
*
|
||||
* @param expression the SpEL expression, must not be {@literal null} or empty.
|
||||
* @param params must not be {@literal null}
|
||||
* @return new instance of {@link ExpressionBucketOperationBuilderSupport} to create {@link BucketOperation}.
|
||||
* @return
|
||||
*/
|
||||
public abstract ExpressionBucketOperationBuilderSupport<B, T> andOutputExpression(String expression,
|
||||
Object... params);
|
||||
@@ -113,7 +114,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
* resulting bucket documents.
|
||||
*
|
||||
* @param expression the SpEL expression, must not be {@literal null} or empty.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public abstract B andOutput(AggregationExpression expression);
|
||||
|
||||
@@ -123,14 +124,14 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
* {@literal fieldName}.
|
||||
*
|
||||
* @param fieldName must not be {@literal null} or empty.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public abstract B andOutput(String fieldName);
|
||||
|
||||
/**
|
||||
* Creates a new {@link BucketOperationSupport} given to add a count field to the resulting bucket documents.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B andOutputCount() {
|
||||
return andOutput(new AggregationExpression() {
|
||||
@@ -230,7 +231,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
* Generates a builder for a {@code $sum}-expression. <br />
|
||||
* Count expressions are emulated via {@code $sum: 1}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B count() {
|
||||
return sum(1);
|
||||
@@ -239,7 +240,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for a {@code $sum}-expression for the current value.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B sum() {
|
||||
return apply(Accumulators.SUM);
|
||||
@@ -248,8 +249,8 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for a {@code $sum}-expression for the given {@literal value}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public B sum(Number value) {
|
||||
return apply(new OperationOutput(Accumulators.SUM.getMongoOperator(), Collections.singleton(value)));
|
||||
@@ -258,7 +259,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for an {@code $last}-expression for the current value..
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B last() {
|
||||
return apply(Accumulators.LAST);
|
||||
@@ -267,7 +268,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for a {@code $first}-expression the current value.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B first() {
|
||||
return apply(Accumulators.FIRST);
|
||||
@@ -276,7 +277,8 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for an {@code $avg}-expression for the current value.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @param reference
|
||||
* @return
|
||||
*/
|
||||
public B avg() {
|
||||
return apply(Accumulators.AVG);
|
||||
@@ -285,7 +287,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for an {@code $min}-expression for the current value.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B min() {
|
||||
return apply(Accumulators.MIN);
|
||||
@@ -294,7 +296,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for an {@code $max}-expression for the current value.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B max() {
|
||||
return apply(Accumulators.MAX);
|
||||
@@ -303,7 +305,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for an {@code $push}-expression for the current value.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B push() {
|
||||
return apply(Accumulators.PUSH);
|
||||
@@ -312,7 +314,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Generates a builder for an {@code $addToSet}-expression for the current value.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B addToSet() {
|
||||
return apply(Accumulators.ADDTOSET);
|
||||
@@ -323,7 +325,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
*
|
||||
* @param operation the operation name, must not be {@literal null} or empty.
|
||||
* @param values must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public B apply(String operation, Object... values) {
|
||||
|
||||
@@ -340,7 +342,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
* Apply an {@link OperationOutput} to this output.
|
||||
*
|
||||
* @param operationOutput must not be {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected abstract B apply(OperationOutput operationOutput);
|
||||
|
||||
@@ -352,7 +354,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
* Returns the finally to be applied {@link BucketOperation} with the given alias.
|
||||
*
|
||||
* @param alias will never be {@literal null} or empty.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public T as(String alias) {
|
||||
|
||||
@@ -548,7 +550,8 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
public Document toDocument(AggregationOperationContext context) {
|
||||
|
||||
List<Object> operationArguments = getOperationArguments(context);
|
||||
return new Document(operation, operationArguments.size() == 1 ? operationArguments.get(0) : operationArguments);
|
||||
return new Document(operation,
|
||||
operationArguments.size() == 1 ? operationArguments.get(0) : operationArguments);
|
||||
}
|
||||
|
||||
protected List<Object> getOperationArguments(AggregationOperationContext context) {
|
||||
@@ -576,7 +579,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Returns the field that holds the {@link ProjectionOperationBuilder.OperationProjection}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
protected Field getField() {
|
||||
return getExposedField();
|
||||
@@ -586,7 +589,7 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
* Creates a new instance of this {@link OperationOutput} with the given alias.
|
||||
*
|
||||
* @param alias the alias to set
|
||||
* @return new instance of {@link OperationOutput}.
|
||||
* @return
|
||||
*/
|
||||
public OperationOutput withAlias(String alias) {
|
||||
|
||||
@@ -655,8 +658,8 @@ public abstract class BucketOperationSupport<T extends BucketOperationSupport<T,
|
||||
/**
|
||||
* Creates a new {@link AggregationExpressionOutput}.
|
||||
*
|
||||
* @param field must not be {@literal null}.
|
||||
* @param expression must not be {@literal null}.
|
||||
* @param field
|
||||
* @param expression
|
||||
*/
|
||||
protected AggregationExpressionOutput(Field field, AggregationExpression expression) {
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public class ComparisonOperators {
|
||||
* Take the field referenced by given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ComparisonOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ComparisonOperatorFactory valueOf(String fieldReference) {
|
||||
return new ComparisonOperatorFactory(fieldReference);
|
||||
@@ -42,7 +42,7 @@ public class ComparisonOperators {
|
||||
* Take the value resulting from the given {@link AggregationExpression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ComparisonOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ComparisonOperatorFactory valueOf(AggregationExpression expression) {
|
||||
return new ComparisonOperatorFactory(expression);
|
||||
@@ -81,7 +81,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link AggregationExpression} that compares two values.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public Cmp compareTo(String fieldReference) {
|
||||
return createCmp().compareTo(fieldReference);
|
||||
@@ -91,7 +91,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link AggregationExpression} that compares two values.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public Cmp compareTo(AggregationExpression expression) {
|
||||
return createCmp().compareTo(expression);
|
||||
@@ -101,7 +101,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link AggregationExpression} that compares two values.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public Cmp compareToValue(Object value) {
|
||||
return createCmp().compareToValue(value);
|
||||
@@ -116,7 +116,7 @@ public class ComparisonOperators {
|
||||
* value is equal to the value of the referenced field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public Eq equalTo(String fieldReference) {
|
||||
return createEq().equalTo(fieldReference);
|
||||
@@ -127,7 +127,7 @@ public class ComparisonOperators {
|
||||
* value is equal to the expression result.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public Eq equalTo(AggregationExpression expression) {
|
||||
return createEq().equalTo(expression);
|
||||
@@ -138,7 +138,7 @@ public class ComparisonOperators {
|
||||
* value is equal to the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public Eq equalToValue(Object value) {
|
||||
return createEq().equalToValue(value);
|
||||
@@ -153,7 +153,7 @@ public class ComparisonOperators {
|
||||
* value is greater than the value of the referenced field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public Gt greaterThan(String fieldReference) {
|
||||
return createGt().greaterThan(fieldReference);
|
||||
@@ -164,7 +164,7 @@ public class ComparisonOperators {
|
||||
* value is greater than the expression result.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public Gt greaterThan(AggregationExpression expression) {
|
||||
return createGt().greaterThan(expression);
|
||||
@@ -175,7 +175,7 @@ public class ComparisonOperators {
|
||||
* value is greater than the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public Gt greaterThanValue(Object value) {
|
||||
return createGt().greaterThanValue(value);
|
||||
@@ -190,7 +190,7 @@ public class ComparisonOperators {
|
||||
* value is greater than or equivalent to the value of the referenced field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public Gte greaterThanEqualTo(String fieldReference) {
|
||||
return createGte().greaterThanEqualTo(fieldReference);
|
||||
@@ -201,7 +201,7 @@ public class ComparisonOperators {
|
||||
* value is greater than or equivalent to the expression result.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public Gte greaterThanEqualTo(AggregationExpression expression) {
|
||||
return createGte().greaterThanEqualTo(expression);
|
||||
@@ -212,7 +212,7 @@ public class ComparisonOperators {
|
||||
* value is greater than or equivalent to the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public Gte greaterThanEqualToValue(Object value) {
|
||||
return createGte().greaterThanEqualToValue(value);
|
||||
@@ -227,7 +227,7 @@ public class ComparisonOperators {
|
||||
* value is less than the value of the referenced field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public Lt lessThan(String fieldReference) {
|
||||
return createLt().lessThan(fieldReference);
|
||||
@@ -238,7 +238,7 @@ public class ComparisonOperators {
|
||||
* value is less than the expression result.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public Lt lessThan(AggregationExpression expression) {
|
||||
return createLt().lessThan(expression);
|
||||
@@ -249,7 +249,7 @@ public class ComparisonOperators {
|
||||
* value is less than to the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public Lt lessThanValue(Object value) {
|
||||
return createLt().lessThanValue(value);
|
||||
@@ -264,7 +264,7 @@ public class ComparisonOperators {
|
||||
* value is less than or equivalent to the value of the referenced field.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @return
|
||||
*/
|
||||
public Lte lessThanEqualTo(String fieldReference) {
|
||||
return createLte().lessThanEqualTo(fieldReference);
|
||||
@@ -275,7 +275,7 @@ public class ComparisonOperators {
|
||||
* value is less than or equivalent to the expression result.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @return
|
||||
*/
|
||||
public Lte lessThanEqualTo(AggregationExpression expression) {
|
||||
return createLte().lessThanEqualTo(expression);
|
||||
@@ -285,8 +285,8 @@ public class ComparisonOperators {
|
||||
* Creates new {@link AggregationExpression} that compares two values and returns {@literal true} when the first
|
||||
* value is less than or equivalent to the given value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public Lte lessThanEqualToValue(Object value) {
|
||||
return createLte().lessThanEqualToValue(value);
|
||||
@@ -301,7 +301,7 @@ public class ComparisonOperators {
|
||||
* are not equivalent.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public Ne notEqualTo(String fieldReference) {
|
||||
return createNe().notEqualTo(fieldReference);
|
||||
@@ -312,7 +312,7 @@ public class ComparisonOperators {
|
||||
* are not equivalent.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public Ne notEqualTo(AggregationExpression expression) {
|
||||
return createNe().notEqualTo(expression);
|
||||
@@ -323,7 +323,7 @@ public class ComparisonOperators {
|
||||
* are not equivalent.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public Ne notEqualToValue(Object value) {
|
||||
return createNe().notEqualToValue(value);
|
||||
@@ -358,7 +358,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Cmp}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public static Cmp valueOf(String fieldReference) {
|
||||
|
||||
@@ -370,7 +370,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Cmp}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public static Cmp valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -382,7 +382,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Cmp} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public Cmp compareTo(String fieldReference) {
|
||||
|
||||
@@ -394,7 +394,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Cmp} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public Cmp compareTo(AggregationExpression expression) {
|
||||
|
||||
@@ -406,12 +406,12 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Cmp} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Cmp}.
|
||||
* @return
|
||||
*/
|
||||
public Cmp compareToValue(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return new Cmp(append(value, Expand.KEEP_SOURCE));
|
||||
return new Cmp(append(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Eq}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public static Eq valueOf(String fieldReference) {
|
||||
|
||||
@@ -447,7 +447,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Eq}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public static Eq valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -459,7 +459,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Eq} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public Eq equalTo(String fieldReference) {
|
||||
|
||||
@@ -471,7 +471,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Eq} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public Eq equalTo(AggregationExpression expression) {
|
||||
|
||||
@@ -483,12 +483,12 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Eq} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Eq}.
|
||||
* @return
|
||||
*/
|
||||
public Eq equalToValue(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return new Eq(append(value, Expand.KEEP_SOURCE));
|
||||
return new Eq(append(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gt}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public static Gt valueOf(String fieldReference) {
|
||||
|
||||
@@ -524,7 +524,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gt}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public static Gt valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -536,7 +536,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gt} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public Gt greaterThan(String fieldReference) {
|
||||
|
||||
@@ -548,7 +548,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gt} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public Gt greaterThan(AggregationExpression expression) {
|
||||
|
||||
@@ -560,7 +560,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gt} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Gt}.
|
||||
* @return
|
||||
*/
|
||||
public Gt greaterThanValue(Object value) {
|
||||
|
||||
@@ -589,7 +589,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lt}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public static Lt valueOf(String fieldReference) {
|
||||
|
||||
@@ -601,7 +601,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lt}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public static Lt valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -613,7 +613,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lt} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public Lt lessThan(String fieldReference) {
|
||||
|
||||
@@ -625,7 +625,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lt} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public Lt lessThan(AggregationExpression expression) {
|
||||
|
||||
@@ -637,7 +637,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lt} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Lt}.
|
||||
* @return
|
||||
*/
|
||||
public Lt lessThanValue(Object value) {
|
||||
|
||||
@@ -666,7 +666,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gte}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public static Gte valueOf(String fieldReference) {
|
||||
|
||||
@@ -678,7 +678,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gte}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public static Gte valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -690,7 +690,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gte} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public Gte greaterThanEqualTo(String fieldReference) {
|
||||
|
||||
@@ -702,7 +702,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gte} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public Gte greaterThanEqualTo(AggregationExpression expression) {
|
||||
|
||||
@@ -714,7 +714,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Gte} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Gte}.
|
||||
* @return
|
||||
*/
|
||||
public Gte greaterThanEqualToValue(Object value) {
|
||||
|
||||
@@ -743,7 +743,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lte}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @return
|
||||
*/
|
||||
public static Lte valueOf(String fieldReference) {
|
||||
|
||||
@@ -755,7 +755,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lte}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @return
|
||||
*/
|
||||
public static Lte valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -767,7 +767,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lte} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @return
|
||||
*/
|
||||
public Lte lessThanEqualTo(String fieldReference) {
|
||||
|
||||
@@ -779,7 +779,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lte} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @return
|
||||
*/
|
||||
public Lte lessThanEqualTo(AggregationExpression expression) {
|
||||
|
||||
@@ -791,7 +791,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Lte} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Lte}.
|
||||
* @return
|
||||
*/
|
||||
public Lte lessThanEqualToValue(Object value) {
|
||||
|
||||
@@ -820,7 +820,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Ne}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public static Ne valueOf(String fieldReference) {
|
||||
|
||||
@@ -832,7 +832,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Ne}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public static Ne valueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -844,7 +844,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Ne} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public Ne notEqualTo(String fieldReference) {
|
||||
|
||||
@@ -856,7 +856,7 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Ne} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public Ne notEqualTo(AggregationExpression expression) {
|
||||
|
||||
@@ -868,12 +868,12 @@ public class ComparisonOperators {
|
||||
* Creates new {@link Eq} with all previously added arguments appending the given one.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Ne}.
|
||||
* @return
|
||||
*/
|
||||
public Ne notEqualToValue(Object value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
return new Ne(append(value, Expand.KEEP_SOURCE));
|
||||
return new Ne(append(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ConditionalOperators {
|
||||
* Take the field referenced by given {@literal fieldReference}.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link ConditionalOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ConditionalOperatorFactory when(String fieldReference) {
|
||||
return new ConditionalOperatorFactory(fieldReference);
|
||||
@@ -53,7 +53,7 @@ public class ConditionalOperators {
|
||||
* Take the value resulting from the given {@literal expression}.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link ConditionalOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ConditionalOperatorFactory when(AggregationExpression expression) {
|
||||
return new ConditionalOperatorFactory(expression);
|
||||
@@ -63,7 +63,7 @@ public class ConditionalOperators {
|
||||
* Take the value resulting from the given {@literal criteriaDefinition}.
|
||||
*
|
||||
* @param criteriaDefinition must not be {@literal null}.
|
||||
* @return new instance of {@link ConditionalOperatorFactory}.
|
||||
* @return
|
||||
*/
|
||||
public static ConditionalOperatorFactory when(CriteriaDefinition criteriaDefinition) {
|
||||
return new ConditionalOperatorFactory(criteriaDefinition);
|
||||
@@ -75,7 +75,7 @@ public class ConditionalOperators {
|
||||
* instances of undefined values or missing fields, returns the value of the replacement expression.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link IfNull.ThenBuilder} to create {@link IfNull}.
|
||||
* @return
|
||||
*/
|
||||
public static IfNull.ThenBuilder ifNull(String fieldReference) {
|
||||
|
||||
@@ -89,7 +89,7 @@ public class ConditionalOperators {
|
||||
* instances of undefined values or missing fields, returns the value of the replacement expression.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link IfNull.ThenBuilder} to create {@link IfNull}.
|
||||
* @return
|
||||
*/
|
||||
public static IfNull.ThenBuilder ifNull(AggregationExpression expression) {
|
||||
|
||||
@@ -103,7 +103,7 @@ public class ConditionalOperators {
|
||||
* out of the control flow.
|
||||
*
|
||||
* @param conditions must not be {@literal null}.
|
||||
* @return new instance of {@link Switch}.
|
||||
* @return
|
||||
*/
|
||||
public static Switch switchCases(CaseOperator... conditions) {
|
||||
return Switch.switchCases(conditions);
|
||||
@@ -115,7 +115,7 @@ public class ConditionalOperators {
|
||||
* out of the control flow.
|
||||
*
|
||||
* @param conditions must not be {@literal null}.
|
||||
* @return new instance of {@link Switch}.
|
||||
* @return
|
||||
*/
|
||||
public static Switch switchCases(List<CaseOperator> conditions) {
|
||||
return Switch.switchCases(conditions);
|
||||
@@ -176,7 +176,7 @@ public class ConditionalOperators {
|
||||
* return expressions.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link OtherwiseBuilder} to create {@link Cond}.
|
||||
* @return
|
||||
*/
|
||||
public OtherwiseBuilder then(Object value) {
|
||||
|
||||
@@ -189,7 +189,7 @@ public class ConditionalOperators {
|
||||
* return expressions.
|
||||
*
|
||||
* @param expression must not be {@literal null}.
|
||||
* @return new instance of {@link OtherwiseBuilder} to create {@link Cond}.
|
||||
* @return
|
||||
*/
|
||||
public OtherwiseBuilder thenValueOf(AggregationExpression expression) {
|
||||
|
||||
@@ -202,7 +202,7 @@ public class ConditionalOperators {
|
||||
* return expressions.
|
||||
*
|
||||
* @param fieldReference must not be {@literal null}.
|
||||
* @return new instance of {@link OtherwiseBuilder} to create {@link Cond}.
|
||||
* @return
|
||||
*/
|
||||
public OtherwiseBuilder thenValueOf(String fieldReference) {
|
||||
|
||||
@@ -233,9 +233,9 @@ public class ConditionalOperators {
|
||||
* field references}, {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be
|
||||
* converted to a simple MongoDB type.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @see <a href=
|
||||
* "https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/">https://docs.mongodb.com/manual/reference/operator/aggregation/ifNull/</a>
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public static class IfNull implements AggregationExpression {
|
||||
|
||||
@@ -251,9 +251,9 @@ public class ConditionalOperators {
|
||||
/**
|
||||
* Creates new {@link IfNull}.
|
||||
*
|
||||
* @param fieldReference the field to check for a {@literal null} value, field reference must not be
|
||||
* {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @param fieldReference the field to check for a {@literal null} value, field reference must not be {@literal null}
|
||||
* .
|
||||
* @return
|
||||
*/
|
||||
public static ThenBuilder ifNull(String fieldReference) {
|
||||
|
||||
@@ -266,7 +266,7 @@ public class ConditionalOperators {
|
||||
*
|
||||
* @param expression the expression to check for a {@literal null} value, field reference must not be
|
||||
* {@literal null}.
|
||||
* @return never {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public static ThenBuilder ifNull(AggregationExpression expression) {
|
||||
|
||||
@@ -338,19 +338,19 @@ public class ConditionalOperators {
|
||||
* @param value the value to be used if the {@code $ifNull} condition evaluates {@literal true}. Can be a
|
||||
* {@link Document}, a value that is supported by MongoDB or a value that can be converted to a MongoDB
|
||||
* representation but must not be {@literal null}.
|
||||
* @return new instance of {@link IfNull}.
|
||||
* @return
|
||||
*/
|
||||
IfNull then(Object value);
|
||||
|
||||
/**
|
||||
* @param fieldReference the field holding the replacement value, must not be {@literal null}.
|
||||
* @return new instance of {@link IfNull}.
|
||||
* @return
|
||||
*/
|
||||
IfNull thenValueOf(String fieldReference);
|
||||
|
||||
/**
|
||||
* @param expression the expression yielding to the replacement value, must not be {@literal null}.
|
||||
* @return new instance of {@link IfNull}.
|
||||
* @return
|
||||
*/
|
||||
IfNull thenValueOf(AggregationExpression expression);
|
||||
}
|
||||
@@ -461,12 +461,6 @@ public class ConditionalOperators {
|
||||
return new Switch(Collections.<String, Object> singletonMap("branches", new ArrayList<CaseOperator>(conditions)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default value.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link Switch}.
|
||||
*/
|
||||
public Switch defaultTo(Object value) {
|
||||
return new Switch(append("default", value));
|
||||
}
|
||||
@@ -528,7 +522,7 @@ public class ConditionalOperators {
|
||||
* Set the then {@literal value}.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @return new instance of {@link CaseOperator}.
|
||||
* @return
|
||||
*/
|
||||
CaseOperator then(Object value);
|
||||
}
|
||||
@@ -542,10 +536,10 @@ public class ConditionalOperators {
|
||||
* {@link AggregationExpression expressions}, values of simple MongoDB types or values that can be converted to a
|
||||
* simple MongoDB type.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @see <a href=
|
||||
* "https://docs.mongodb.com/manual/reference/operator/aggregation/cond/">https://docs.mongodb.com/manual/reference/operator/aggregation/cond/</a>
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public static class Cond implements AggregationExpression {
|
||||
|
||||
@@ -670,6 +664,7 @@ public class ConditionalOperators {
|
||||
}
|
||||
|
||||
clauses.add(new Document(key, args));
|
||||
|
||||
} else if (predicate instanceof Document) {
|
||||
|
||||
Document nested = (Document) predicate;
|
||||
@@ -685,6 +680,7 @@ public class ConditionalOperators {
|
||||
args.add(nested.get(s));
|
||||
clauses.add(new Document(s, args));
|
||||
}
|
||||
|
||||
} else if (!isKeyword(key)) {
|
||||
|
||||
List<Object> args = new ArrayList<Object>();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user