Skip to content

Commit 4ad463a

Browse files
feat: Add support for vector search with Query#findNearest (#1827)
* Add support for vector search with Query#findNearest --------- Co-authored-by: cloud-java-bot <[email protected]>
1 parent dbe4c82 commit 4ad463a

15 files changed

+2647
-542
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ If you are using Maven without the BOM, add this to your dependencies:
4242
<dependency>
4343
<groupId>com.google.cloud</groupId>
4444
<artifactId>google-cloud-firestore</artifactId>
45-
<version>3.26.4</version>
45+
<version>3.26.5</version>
4646
</dependency>
4747

4848
```

google-cloud-firestore/clirr-ignored-differences.xml

+8
Original file line numberDiff line numberDiff line change
@@ -306,4 +306,12 @@
306306
<className>com/google/cloud/firestore/encoding/CustomClassMapper</className>
307307
<to>*</to>
308308
</difference>
309+
310+
<!-- GenericQuerySnapshot -->
311+
<difference>
312+
<differenceType>7002</differenceType>
313+
<className>com/google/cloud/firestore/QuerySnapshot</className>
314+
<method>com.google.cloud.firestore.Query getQuery()</method>
315+
</difference>
316+
309317
</differences>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.firestore;
18+
19+
import com.google.cloud.Timestamp;
20+
import com.google.cloud.firestore.encoding.CustomClassMapper;
21+
import com.google.common.collect.ImmutableList;
22+
import java.util.ArrayList;
23+
import java.util.Collections;
24+
import java.util.Iterator;
25+
import java.util.List;
26+
import java.util.Objects;
27+
import javax.annotation.Nonnull;
28+
29+
/**
30+
* Abstract. A GenericQuerySnapshot represents the results of a query that returns documents. It can
31+
* contain zero or more DocumentSnapshot objects.
32+
*/
33+
public abstract class GenericQuerySnapshot<QueryT> implements Iterable<QueryDocumentSnapshot> {
34+
protected final QueryT query;
35+
protected final Timestamp readTime;
36+
37+
private List<DocumentChange> documentChanges;
38+
private final List<QueryDocumentSnapshot> documents;
39+
40+
// Elevated access level for mocking.
41+
protected GenericQuerySnapshot(
42+
QueryT query,
43+
Timestamp readTime,
44+
@Nonnull final List<QueryDocumentSnapshot> documents,
45+
final List<DocumentChange> documentChanges) {
46+
this.query = query;
47+
this.readTime = readTime;
48+
this.documentChanges =
49+
documentChanges != null ? Collections.unmodifiableList(documentChanges) : documentChanges;
50+
this.documents = Collections.unmodifiableList(documents);
51+
}
52+
53+
/**
54+
* Returns the query for the snapshot.
55+
*
56+
* @return The backing query that produced this snapshot.
57+
*/
58+
@Nonnull
59+
public QueryT getQuery() {
60+
return query;
61+
}
62+
63+
/**
64+
* Returns the time at which this snapshot was read.
65+
*
66+
* @return The read time of this snapshot.
67+
*/
68+
@Nonnull
69+
public Timestamp getReadTime() {
70+
return readTime;
71+
}
72+
73+
/**
74+
* Returns the documents in this QuerySnapshot as a List in order of the query.
75+
*
76+
* @return The list of documents.
77+
*/
78+
@Nonnull
79+
public List<QueryDocumentSnapshot> getDocuments() {
80+
return this.documents;
81+
}
82+
83+
/** Returns true if there are no documents in the QuerySnapshot. */
84+
public boolean isEmpty() {
85+
return this.size() == 0;
86+
}
87+
88+
@Nonnull
89+
public Iterator<QueryDocumentSnapshot> iterator() {
90+
return getDocuments().iterator();
91+
}
92+
93+
/**
94+
* Returns the contents of the documents in the QuerySnapshot, converted to the provided class, as
95+
* a list.
96+
*
97+
* @param clazz The POJO type used to convert the documents in the list.
98+
*/
99+
@Nonnull
100+
public <T> List<T> toObjects(@Nonnull Class<T> clazz) {
101+
List<QueryDocumentSnapshot> documents = getDocuments();
102+
List<T> results = new ArrayList<>(documents.size());
103+
for (DocumentSnapshot documentSnapshot : documents) {
104+
results.add(
105+
CustomClassMapper.convertToCustomClass(
106+
documentSnapshot.getData(), clazz, documentSnapshot.getReference()));
107+
}
108+
109+
return results;
110+
}
111+
112+
/**
113+
* Returns the list of documents that changed since the last snapshot. If it's the first snapshot
114+
* all documents will be in the list as added changes.
115+
*
116+
* @return The list of documents that changed since the last snapshot.
117+
*/
118+
@Nonnull
119+
public List<DocumentChange> getDocumentChanges() {
120+
if (documentChanges == null) {
121+
synchronized (documents) {
122+
if (documentChanges == null) {
123+
int size = documents.size();
124+
ImmutableList.Builder<DocumentChange> builder =
125+
ImmutableList.builderWithExpectedSize(size);
126+
for (int i = 0; i < size; ++i) {
127+
builder.add(new DocumentChange(documents.get(i), DocumentChange.Type.ADDED, -1, i));
128+
}
129+
documentChanges = builder.build();
130+
}
131+
}
132+
}
133+
134+
return documentChanges;
135+
}
136+
137+
/** Returns the number of DocumentSnapshots in this snapshot. */
138+
public int size() {
139+
return getDocuments().size();
140+
}
141+
142+
/**
143+
* Tests for equality with this object.
144+
*
145+
* @param o is tested for equality with this object.
146+
* @return `true` if equal, otherwise `false`
147+
*/
148+
public boolean equals(Object o) {
149+
if (this == o) {
150+
return true;
151+
}
152+
if (o == null || getClass() != o.getClass()) {
153+
return false;
154+
}
155+
GenericQuerySnapshot that = (GenericQuerySnapshot) o;
156+
return Objects.equals(query, that.query)
157+
&& Objects.equals(this.getDocumentChanges(), that.getDocumentChanges())
158+
&& Objects.equals(this.getDocuments(), that.getDocuments());
159+
}
160+
161+
@Override
162+
public int hashCode() {
163+
return Objects.hash(query, this.getDocumentChanges(), this.getDocuments());
164+
}
165+
}

0 commit comments

Comments
 (0)