From a6a5c7ded17a2c5db6b731d4f2ada39b41e876ca Mon Sep 17 00:00:00 2001 From: Nikolay Karadzhov Date: Mon, 18 Aug 2025 16:08:08 +0300 Subject: [PATCH] fix(search): properly decide if response has docs fixes: #3056 --- packages/search/lib/commands/SEARCH.spec.ts | 79 +++++++++++++++++++++ packages/search/lib/commands/SEARCH.ts | 3 +- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/packages/search/lib/commands/SEARCH.spec.ts b/packages/search/lib/commands/SEARCH.spec.ts index ab480808ff..97e1a9a988 100644 --- a/packages/search/lib/commands/SEARCH.spec.ts +++ b/packages/search/lib/commands/SEARCH.spec.ts @@ -326,5 +326,84 @@ describe('FT.SEARCH', () => { } ); }, GLOBAL.SERVERS.OPEN); + + testUtils.testWithClient('properly parse content/nocontent scenarios', async client => { + + const indexName = 'foo'; + await client.ft.create( + indexName, + { + itemOrder: { + type: 'NUMERIC', + SORTABLE: true, + }, + name: { + type: 'TEXT', + }, + }, + { + ON: 'HASH', + PREFIX: 'item:', + } + ); + + await client.hSet("item:1", { + itemOrder: 1, + name: "First item", + }); + + await client.hSet("item:2", { + itemOrder: 2, + name: "Second item", + }); + + await client.hSet("item:3", { + itemOrder: 3, + name: "Third item", + }); + + // Search with SORTBY and LIMIT + let result = await client.ft.search(indexName, "@itemOrder:[0 10]", { + SORTBY: { + BY: "itemOrder", + DIRECTION: "ASC", + }, + LIMIT: { + from: 0, + size: 1, // only get first result + }, + }); + + assert.equal(result.total, 3, "Result's `total` value reflects the total scanned documents"); + assert.equal(result.documents.length, 1); + let doc = result.documents[0]; + assert.equal(doc.id, 'item:1'); + assert.equal(doc.value.itemOrder, '1'); + assert.equal(doc.value.name, 'First item'); + + await client.del("item:3"); + + // Search again after removing item:3 + result = await client.ft.search(indexName, "@itemOrder:[0 10]", { + SORTBY: { + BY: "itemOrder", + DIRECTION: "ASC", + }, + LIMIT: { + from: 0, + size: 1, // only get first result + }, + }); + + assert.equal(result.total, 2, "Result's `total` value reflects the total scanned documents"); + assert.equal(result.documents.length, 1); + doc = result.documents[0]; + assert.equal(doc.id, 'item:1'); + assert.equal(doc.value.itemOrder, '1'); + assert.equal(doc.value.name, 'First item'); + + + }, GLOBAL.SERVERS.OPEN); + }); }); diff --git a/packages/search/lib/commands/SEARCH.ts b/packages/search/lib/commands/SEARCH.ts index 61e1d8d84d..03779a446c 100644 --- a/packages/search/lib/commands/SEARCH.ts +++ b/packages/search/lib/commands/SEARCH.ts @@ -183,7 +183,8 @@ export default { }, transformReply: { 2: (reply: SearchRawReply): SearchReply => { - const withoutDocuments = (reply[0] + 1 == reply.length) + // if reply[2] is array, then we have content/documents. Otherwise, only ids + const withoutDocuments = reply.length > 2 && !Array.isArray(reply[2]); const documents = []; let i = 1;