How to make FT.SEARCH return the correct types?

I have a node server and a RedisOM db, and am trying to use FT.SEARCH to return results (for performance reasons).

For the most part it works well, but I'm having trouble with arrays (of strings) where it is only returning the first item as a string.

e.g. (I'll try and keep it condensed but with the required details)

const getEntitiesByWhereAndFields = async ({ entity, whereData, fieldsData }) => {

    // Example of incoming parameters:
    // entity: MassEmail
    // whereData: []
    // fieldsData: [
    //  { field: 'createdDateTime', type: 'number' },
    //  { field: 'massEmailText', type: 'string' },
    //  { field: 'massEmailSendToListUsers', type: 'array' }
    // ]

    try {

        // ...other validation code

        // Construct the index name dynamically
        const INDEX_NAME = `${entity}:index`;

        // Construct the query filter based on criteria
        let QUERY_FILTER = whereData.map(condition => `@${condition.whereKey}:{${condition.whereValue}}`).join(' ');
        QUERY_FILTER += ' @isDeleted:{false}';

        // Construct the raw query string with specified fields
        const RAW_QUERY = ['FT.SEARCH', INDEX_NAME, QUERY_FILTER, 'RETURN', String(fieldsData.length), ...fieldsData.map(f => f.field), 'LIMIT', '0', '10000'];
        console.log('RAW_QUERY:', RAW_QUERY);

        // Execute the raw search query directly using the Redis client
        const SEARCH_RESULTS = await client.execute(RAW_QUERY);
        console.log('SEARCH_RESULTS:', SEARCH_RESULTS);

        // ...process results

    } catch (error) {
        console.error('Error fetching getEntitiesByWhereAndFields:', error);
        throw error;
    }
};

Everything is returned as a string.

I can handle and convert strings -> numbers effectively.

Arrays only return the first item as a single string so I cannot do anything with it???

SEARCH_RESULTS: [
    1,
    'MassEmail:01xxxxxxxxxx',
    [
        'createdDateTime',
        '1718702387252',
        'massEmailText',
        '<p>This is only sending to specific users.</p>',
        'massEmailSendToListUsers',
        '01xxxxxxxxxx'
    ]
]

So my question is, how can I return the full array of strings?

Thanks

Upvotes: 0

Views: 79

Answers (1)

I'll leave this here for anyone that faces the same issue.

The problem was the RETURN, so instead of requesting just the fields I wanted I removed that and had a stringified version of the data which I parsed later on and processed as required.

This is a scaled-down essential only version of the code:

const getEntitiesByWhereAndFields = async ({ entity, whereData, fieldsData }) => {

    // ...validate the input data

    try {

        // Construct the index name dynamically
        const INDEX_NAME = `${entity}:index`

        // Construct the query filter based on criteria
        let QUERY_FILTER = whereData.map(condition => `@${condition.whereKey}:{${condition.whereValue}}`).join(' ')
        QUERY_FILTER += ' @isDeleted:{false}'

        // Construct the raw query string
        const RAW_QUERY = ['FT.SEARCH', INDEX_NAME, QUERY_FILTER, 'LIMIT', '0', '10000']

        // Execute the raw search query directly using the Redis client
        const SEARCH_RESULTS = await client.execute(RAW_QUERY)

        // Check if result contains entities
        if (SEARCH_RESULTS.length <= 1) return []

        // Parse the results
        const ENTITIES = []
        const SEARCH_RESULTS_LENGTH = SEARCH_RESULTS.length
        const FIELDS_DATA_LENGTH = fieldsData.length
        for (let i = 1; i < SEARCH_RESULTS_LENGTH; i += 2) {

            // Extract the JSON string from the result
            const JSON_STRING = SEARCH_RESULTS[i + 1][1]

            // Parse the JSON string into an object
            const ENTITY_OBJECT = JSON.parse(JSON_STRING)
            console.log('ENTITY_OBJECT:', ENTITY_OBJECT)

            // ...lots of other processing and cool stuff as required
        }

        // Return the processed data as the response
        return ENTITIES

    } catch (error) {
        console.error('Error fetching getEntitiesByWhereAndFields: ', error)
        throw error
    }
}

The console.log() of the ENTITY_OBJECT will give you the data as a simple JSON to play with 😎

Upvotes: 0

Related Questions