Skip to content

Commit

Permalink
Node: Add command GEOHASH (valkey-io#1997)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjzhang-BQ authored Jul 23, 2024
1 parent 861019c commit 0e8cf5b
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
* Node: Added GeoAdd command ([#1980](https://github.com/valkey-io/valkey-glide/pull/1980))
* Node: Added ZRevRank command ([#1977](https://github.com/valkey-io/valkey-glide/pull/1977))
* Node: Added GeoDist command ([#1988](https://github.com/valkey-io/valkey-glide/pull/1988))
* Node: Added GeoHash command ([#1997](https://github.com/valkey-io/valkey-glide/pull/1997))

#### Breaking Changes
* Node: Update XREAD to return a Map of Map ([#1494](https://github.com/valkey-io/valkey-glide/pull/1494))
Expand Down
25 changes: 25 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
createGeoAdd,
createGeoDist,
createGeoPos,
createGeoHash,
createGet,
createGetBit,
createGetDel,
Expand Down Expand Up @@ -3505,6 +3506,30 @@ export class BaseClient {
);
}

/**
* Returns the `GeoHash` strings representing the positions of all the specified `members` in the sorted set stored at `key`.
*
* See https://valkey.io/commands/geohash/ for more details.
*
* @param key - The key of the sorted set.
* @param members - The array of members whose <code>GeoHash</code> strings are to be retrieved.
* @returns An array of `GeoHash` strings representing the positions of the specified members stored at `key`.
* If a member does not exist in the sorted set, a `null` value is returned for that member.
*
* @example
* ```typescript
* const result = await client.geohash("mySortedSet",["Palermo", "Catania", "NonExisting"]);
* console.log(num); // Output: ["sqc8b49rny0", "sqdtr74hyu0", null]
* ```
*/
public geohash(key: string, members: string[]): Promise<(string | null)[]> {
return this.createWritePromise<(string | null)[]>(
createGeoHash(key, members),
).then((hashes) =>
hashes.map((hash) => (hash === null ? null : "" + hash)),
);
}

/**
* @internal
*/
Expand Down
11 changes: 11 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,17 @@ export function createGeoDist(
return createCommand(RequestType.GeoDist, args);
}

/**
* @internal
*/
export function createGeoHash(
key: string,
members: string[],
): command_request.Command {
const args: string[] = [key].concat(members);
return createCommand(RequestType.GeoHash, args);
}

/**
* @internal
*/
Expand Down
16 changes: 16 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
createFunctionLoad,
createGeoAdd,
createGeoDist,
createGeoHash,
createGeoPos,
createGet,
createGetBit,
Expand Down Expand Up @@ -2057,6 +2058,21 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
): T {
return this.addAndReturn(createGeoDist(key, member1, member2, geoUnit));
}

/**
* Returns the `GeoHash` strings representing the positions of all the specified `members` in the sorted set stored at `key`.
*
* See https://valkey.io/commands/geohash/ for more details.
*
* @param key - The key of the sorted set.
* @param members - The array of members whose <code>GeoHash</code> strings are to be retrieved.
*
* Command Response - An array of `GeoHash` strings representing the positions of the specified members stored at `key`.
* If a member does not exist in the sorted set, a `null` value is returned for that member.
*/
public geohash(key: string, members: string[]): T {
return this.addAndReturn(createGeoHash(key, members));
}
}

/**
Expand Down
38 changes: 38 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4686,6 +4686,44 @@ export function runBaseTests<Context>(config: {
},
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`geohash test_%p`,
async (protocol) => {
await runTest(async (client: BaseClient) => {
const key1 = uuidv4();
const key2 = uuidv4();
const members = ["Palermo", "Catania", "NonExisting"];
const empty: string[] = [];
const expected = ["sqc8b49rny0", "sqdtr74hyu0", null];

// adding the geo locations
const membersToCoordinates = new Map<string, GeospatialData>();
membersToCoordinates.set(
"Palermo",
new GeospatialData(13.361389, 38.115556),
);
membersToCoordinates.set(
"Catania",
new GeospatialData(15.087269, 37.502669),
);
expect(await client.geoadd(key1, membersToCoordinates)).toBe(2);

// checking result with default metric
expect(await client.geohash(key1, members)).toEqual(expected);

// empty members array
expect(await (await client.geohash(key1, empty)).length).toBe(
0,
);

// key exists but holds non-ZSET value
expect(await client.set(key2, "geohash")).toBe("OK");
await expect(client.geohash(key2, members)).rejects.toThrow();
}, protocol);
},
config.timeout,
);
}

export function runCommonTests<Context>(config: {
Expand Down
2 changes: 2 additions & 0 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,8 @@ export async function transactionTest(
args.push(166274.1516);
baseTransaction.geodist(key18, "Palermo", "Catania", GeoUnit.KILOMETERS);
args.push(166.2742);
baseTransaction.geohash(key18, ["Palermo", "Catania", "NonExisting"]);
args.push(["sqc8b49rny0", "sqdtr74hyu0", null]);

const libName = "mylib1C" + uuidv4().replaceAll("-", "");
const funcName = "myfunc1c" + uuidv4().replaceAll("-", "");
Expand Down

0 comments on commit 0e8cf5b

Please sign in to comment.