Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC-4345 added testable JSON index/query example #2864

Open
wants to merge 4 commits into
base: emb-examples
Choose a base branch
from
Open
Changes from 3 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
149 changes: 149 additions & 0 deletions doctests/home-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// EXAMPLE: js_home_json
// REMOVE_START
import assert from 'assert';
// REMOVE_END
// STEP_START import
import {
createClient,
SchemaFieldTypes,
AggregateGroupByReducers,
AggregateSteps,
} from 'redis';
// STEP_END

// STEP_START connect
const client = await createClient();
await client.connect();
// STEP_END
// REMOVE_START
try {
await client.ft.dropIndex('idx:users', { DD: true });
} catch{}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for this is that dropIndex generally throws an error if you try to drop an index that doesn't exist (at least in the clients for other languages). It seemed to work OK without the try...catch locally, but I got an error from the CI when I made the PR. I assumed the try...catch was required and it fixed the error. If I'm doing this the wrong way or misinterpreting the build error then please let me know.


await client.del('user:1', 'user:2', 'user:3');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FT.DROPINDEX idx:users DD already delete the keys, why are we deleting them again?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Often, there isn't an existing index (hence the try...catch as I mentioned in the previous reply), so presumably the keys don't get deleted in this case. However, keys like user:1, etc, are common in docs and test code. If user:1 exists but isn't a JSON key then you'll get the "wrong kind of value" error. If you think I'm being overly cautious here then I'll remove the client.del here, but I have seen this kind of thing happen occasionally.

// REMOVE_END

// STEP_START create_data
var user1 = {
name: "Paul John",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use ' instead of "
use const/let instead of var
add missing ;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found/replaced these throughout the file now.

email: "[email protected]",
age: 42,
city: "London"
}

var user2 = {
name: "Eden Zamir",
email: "[email protected]",
age: 29,
city: "Tel Aviv"
}

var user3 = {
name: "Paul Zamir",
email: "[email protected]",
age: 35,
city: "Tel Aviv"
}
// STEP_END

// STEP_START make_index
await client.ft.create('idx:users', {
'$.name': {
type: SchemaFieldTypes.TEXT,
AS: 'name'
},
"$.city": {
type: SchemaFieldTypes.TEXT,
AS: 'city'
},
'$.age': {
type: SchemaFieldTypes.NUMERIC,
AS: 'age'
}
}, {
ON: 'JSON',
PREFIX: 'user:'
});
// STEP_END

// STEP_START add_data
var user1Added = await client.json.set('user:1', '$', user1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no reason to make 3 round trips for 3 SET, you can do:

const [user1Reply, user2Reply, user3Reply] = await Promise.all([
  client.json.set('user:1', '$', user1),
  client.json.set('user:2', '$', user2),
  client.json.set('user:3', '$', user3)
]);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good tip, thanks.

var user2Added = await client.json.set('user:2', '$', user2);
var user3Added = await client.json.set('user:3', '$', user3);
// STEP_END
// REMOVE_START
assert.equal('OK', user1Added);
assert.equal('OK', user2Added);
assert.equal('OK', user3Added);
// REMOVE_END

// STEP_START query1
var findPaulResult = await client.ft.search('idx:users', 'Paul @age:[30 40]');

console.log(findPaulResult.total); // >>> 1

findPaulResult.documents.forEach(doc => {
console.log(`ID: ${doc.id}, name: ${doc.value.name}, age: ${doc.value.age}`);
});
// >>> ID: user:3, name: Paul Zamir, age: 35
// STEP_END
// REMOVE_START
assert.strictEqual(1, findPaulResult.total);

var paulDoc = findPaulResult.documents[0];

assert.equal('user:3', paulDoc.id);
// REMOVE_END

// STEP_START query2
var citiesResult = await client.ft.search('idx:users', '*',{
RETURN: "city"
});

console.log(citiesResult.total); // >>> 3

citiesResult.documents.forEach(cityDoc => {
console.log(cityDoc.value);
});
// >>> {city: 'London'}
// >>> {city: 'Tel Aviv'}
// >>> {city: 'Tel Aviv'}
// STEP_END
// REMOVE_START
assert.strictEqual(3, citiesResult.total);

citiesResult.documents.sort((a, b)=> a.id < b.id);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we sorting on the client side and not using RediSearch it self?!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just for the test code. For other client examples I've written, the order of the documents returned is not deterministic, so you need to sort before using the asserts, otherwise you get an occasionally flaky test. The reason I don't add the sort option to the command is simply that the other client examples don't use the sort option here - just keeping them all consistent.

assert.equal('user:1', citiesResult.documents[0].id);
assert.equal('user:2', citiesResult.documents[1].id);
assert.equal('user:3', citiesResult.documents[2].id);
// REMOVE_END

// STEP_START query3
var aggResult = await client.ft.aggregate('idx:users', '*', {
STEPS: [{
type: AggregateSteps.GROUPBY,
properties: '@city',
REDUCE: [{
type: AggregateGroupByReducers.COUNT,
AS: 'count'
}]
}]
});

console.log(aggResult.total); // >>> 2

aggResult.results.forEach(result => {
console.log(`${result.city} - ${result.count}`);
});
// >>> London - 1
// >>> Tel Aviv - 2
// STEP_END
// REMOVE_START
assert.strictEqual(2, aggResult.total);

aggResult.results.sort((a, b) => a.city < b.city);
assert.equal('London - 1', `${aggResult.results[0].city} - ${aggResult.results[0].count}`);
assert.equal('Tel Aviv - 2', `${aggResult.results[1].city} - ${aggResult.results[1].count}`)
// REMOVE_END

await client.quit();
Loading