Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<assertj-core.version>3.27.4</assertj-core.version>
<jparams.version>1.0.4</jparams.version>
<mockito.version>5.19.0</mockito.version>
<slf4j.version>2.0.17</slf4j.version>
<slf4j.version>1.7.36</slf4j.version>
<logback.version>1.5.18</logback.version>
<mock-server.version>5.14.0</mock-server.version>
<jackson.version>2.19.2</jackson.version>
Expand Down
67 changes: 67 additions & 0 deletions src/it/java/io/weaviate/integration/SearchITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.weaviate.client6.v1.api.collections.query.Metadata;
import io.weaviate.client6.v1.api.collections.query.QueryMetadata;
import io.weaviate.client6.v1.api.collections.query.QueryResponseGroup;
import io.weaviate.client6.v1.api.collections.query.SortBy;
import io.weaviate.client6.v1.api.collections.query.Where;
import io.weaviate.containers.Container;
import io.weaviate.containers.Container.ContainerGroup;
Expand Down Expand Up @@ -257,6 +258,72 @@ public void testFetchObjectsWithFilters() throws IOException {

}

@Test
public void testFetchObjectsWithSort() throws Exception {
var nsNumbers = ns("Numbers");

// Arrange
client.collections.create(nsNumbers,
c -> c.properties(Property.integer("value")));

var numbers = client.collections.use(nsNumbers);

var one = numbers.data.insert(Map.of("value", 1L));
var two = numbers.data.insert(Map.of("value", 2L));
var three = numbers.data.insert(Map.of("value", 3L));

// Act: sort ascending
var asc = numbers.query.fetchObjects(
q -> q.sort(SortBy.property("value")));

Assertions.assertThat(asc.objects())
.as("value asc")
.hasSize(3)
.extracting(WeaviateObject::properties)
.extracting(object -> object.get("value"))
.containsExactly(1L, 2L, 3L);

// Act: sort descending
var desc = numbers.query.fetchObjects(
q -> q.sort(SortBy.property("value").desc()));

Assertions.assertThat(desc.objects())
.as("value desc")
.hasSize(3)
.extracting(WeaviateObject::properties)
.extracting(object -> object.get("value"))
.containsExactly(3L, 2L, 1L);

// Act: sort by creation time asc
var created = numbers.query.fetchObjects(
q -> q.sort(SortBy.creationTime()));

Assertions.assertThat(created.objects())
.as("create time asc")
.hasSize(3)
.extracting(WeaviateObject::uuid)
.containsExactly(one.uuid(), two.uuid(), three.uuid());

// Act: sort by updated time desc
numbers.data.update(one.uuid(), upd -> upd.properties(Map.of("value", -1L)));
Thread.sleep(10);
numbers.data.update(two.uuid(), upd -> upd.properties(Map.of("value", -2L)));
Thread.sleep(10);
numbers.data.update(three.uuid(), upd -> upd.properties(Map.of("value", -3L)));

var updated = numbers.query.fetchObjects(
q -> q.sort(
// Both sort operators imply ordering 3-2-1
SortBy.lastUpdateTime().desc(),
SortBy.property("value").asc()));

Assertions.assertThat(updated.objects())
.as("last update time desc + value asc")
.hasSize(3)
.extracting(WeaviateObject::uuid)
.containsExactly(three.uuid(), two.uuid(), one.uuid());
}

@Test
public void testBm25() throws IOException, InterruptedException, ExecutionException {
var nsWords = ns("Words");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,54 @@
package io.weaviate.client6.v1.api.collections.query;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

import io.weaviate.client6.v1.internal.ObjectBuilder;
import io.weaviate.client6.v1.internal.grpc.protocol.WeaviateProtoSearchGet;

public record FetchObjects(BaseQueryOptions common) implements QueryOperator {
public record FetchObjects(BaseQueryOptions common, List<SortBy> sortBy) implements QueryOperator {

public static FetchObjects of(Function<Builder, ObjectBuilder<FetchObjects>> fn) {
return fn.apply(new Builder()).build();
}

public FetchObjects(Builder builder) {
this(builder.baseOptions());
this(builder.baseOptions(), builder.sortBy);
}

public static class Builder extends BaseQueryOptions.Builder<Builder, FetchObjects> {
private final List<SortBy> sortBy = new ArrayList<>();

/**
* Sort query results. Default sorted order is ascending, use
* {@link SortBy#desc} to reverse it.
*
* <pre>{@code
* sort(SortBy.property("age"), SortBy.creationTime().desc());
* }</pre>
*
* @param sortBy A list of sort-by clauses in the order
* they should be applied.
* @return This builder.
*/
public Builder sort(SortBy... sortBy) {
return sort(Arrays.asList(sortBy));
}

/**
* Sort query results. Default sorted order is ascending, use
* {@link SortBy#desc} to reverse it.
*
* @param sortBy A list of sort-by clauses in the order
* they should be applied.
* @return This builder.
*/
public Builder sort(List<SortBy> sortBy) {
this.sortBy.addAll(sortBy);
return this;
}

@Override
public final FetchObjects build() {
Expand All @@ -26,5 +59,11 @@ public final FetchObjects build() {
@Override
public void appendTo(WeaviateProtoSearchGet.SearchRequest.Builder req) {
common.appendTo(req);

for (final var sort : sortBy) {
req.addSortBy(WeaviateProtoSearchGet.SortBy.newBuilder()
.addAllPath(sort.path())
.setAscending(sort.ascending()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.weaviate.client6.v1.api.collections.query;

import java.util.List;

public record SortBy(List<String> path, boolean ascending) {
/**
* Sort by object property. Ascending order by default.
*
* @see #desc() to sort in descending order.
*/
public static SortBy property(String property) {
return new SortBy(List.of(property), true);
}

/**
* Sort by object creation time. Ascending order by default.
*
* @see #desc() to sort in descending order.
*/
public static SortBy creationTime() {
return property("_creationTimeUnix");
}

/**
* Sort by object last update time. Ascending order by default.
*
* @see #desc() to sort in descending order.
*/
public static SortBy lastUpdateTime() {
return property("_lastUpdateTimeUnix");
}

/**
* Sort in ascending order.
*
* <p>
* Example:
*
* <pre>{@code
* SortBy.property("name").asc();
* }</pre>
*/
public SortBy asc() {
return new SortBy(path, true);
}

/**
* Sort in descending order.
*
* <p>
* Example:
*
* <pre>{@code
* SortBy.property("name").desc();
* }</pre>
*/
public SortBy desc() {
return new SortBy(path, false);
}
}