diff --git a/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml b/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml
index 922f1a822..abb5d595a 100644
--- a/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml
+++ b/java/google/registry/env/common/default/WEB-INF/datastore-indexes.xml
@@ -77,6 +77,12 @@
+
+
+
+
+
+
diff --git a/java/google/registry/rdap/RdapDomainSearchAction.java b/java/google/registry/rdap/RdapDomainSearchAction.java
index 677d8c0fd..40ad7d96f 100644
--- a/java/google/registry/rdap/RdapDomainSearchAction.java
+++ b/java/google/registry/rdap/RdapDomainSearchAction.java
@@ -238,12 +238,18 @@ public class RdapDomainSearchAction extends RdapActionBase {
/** Searches for domains by domain name with a TLD suffix. */
private RdapSearchResults searchByDomainNameByTld(String tld, DateTime now) {
- // Since we aren't searching on fullyQualifiedDomainName, we can perform our one allowed
- // inequality query on deletion time.
+ // Even though we are not searching on fullyQualifiedDomainName, we want the results to come
+ // back ordered by name, so we are still in the same boat as
+ // searchByDomainNameWithInitialString, unable to perform an inequality query on deletion time.
+ // Don't use queryItems, because it doesn't handle pending deletes.
Query query =
- queryItems(
- DomainResource.class, "tld", tld, shouldIncludeDeleted(), rdapResultSetMaxSize + 1);
- return makeSearchResults(getMatchingResources(query, shouldIncludeDeleted(), now), now);
+ ofy()
+ .load()
+ .type(DomainResource.class)
+ .filter("tld", tld)
+ .order("fullyQualifiedDomainName")
+ .limit(RESULT_SET_SIZE_SCALING_FACTOR * rdapResultSetMaxSize);
+ return makeSearchResults(getMatchingResources(query, true, now), now);
}
/**
diff --git a/javatests/google/registry/rdap/RdapDomainSearchActionTest.java b/javatests/google/registry/rdap/RdapDomainSearchActionTest.java
index a03fc5e3d..6c4e4b33f 100644
--- a/javatests/google/registry/rdap/RdapDomainSearchActionTest.java
+++ b/javatests/google/registry/rdap/RdapDomainSearchActionTest.java
@@ -855,7 +855,7 @@ public class RdapDomainSearchActionTest {
@Test
public void testDomainMatch_star_lol_found() throws Exception {
assertThat(generateActualJson(RequestType.NAME, "*.lol"))
- .isEqualTo(generateExpectedJsonForTwoDomains("cat2.lol", "17-LOL", "cat.lol", "C-LOL"));
+ .isEqualTo(generateExpectedJsonForTwoDomains("cat.lol", "C-LOL", "cat2.lol", "17-LOL"));
assertThat(response.getStatus()).isEqualTo(200);
}
@@ -863,7 +863,7 @@ public class RdapDomainSearchActionTest {
public void testDomainMatch_star_lol_found_sameRegistrarRequested() throws Exception {
action.registrarParam = Optional.of("evilregistrar");
assertThat(generateActualJson(RequestType.NAME, "*.lol"))
- .isEqualTo(generateExpectedJsonForTwoDomains("cat2.lol", "17-LOL", "cat.lol", "C-LOL"));
+ .isEqualTo(generateExpectedJsonForTwoDomains("cat.lol", "C-LOL", "cat2.lol", "17-LOL"));
assertThat(response.getStatus()).isEqualTo(200);
}
@@ -1056,6 +1056,22 @@ public class RdapDomainSearchActionTest {
"rdap_domains_four_truncated.json");
}
+ @Test
+ public void testDomainMatch_tldSearchOrderedProperly() throws Exception {
+ createManyDomainsAndHosts(4, 1, 2);
+ assertThat(generateActualJson(RequestType.NAME, "*.lol"))
+ .isEqualTo(readMultiDomainFile(
+ "rdap_domains_four_truncated.json",
+ "cat.lol",
+ "C-LOL",
+ "cat2.lol",
+ "17-LOL",
+ "domain1.lol",
+ "46-LOL",
+ "domain2.lol",
+ "45-LOL"));
+ }
+
@Test
public void testDomainMatch_reallyTruncatedResultsSet() throws Exception {
// Don't use 10 or more domains for this test, because domain10.lol will come before