Node.js 根据其他表的行建议结果

Node.js 根据其他表的行建议结果,node.js,postgresql,Node.js,Postgresql,我在postgresql数据库中有两个表。表1=空缺,表2=搜索查询。我想根据用户之前的搜索查询向他们推荐职位空缺(只有最后10个搜索查询是重要的) 当用户搜索空缺时,他必须输入一些关键字,并且他可以选择一个位置(单个)、一个公司(单个)、多个部门(多个)、多个工作域(多个)和就业类型(多个) 行业和工作领域是关键,如“建筑”、“销售”、“技术”。就业类型、公司和地点是UUID,在其他表中有更多的规定(因为新公司可以加入,新地点可以加入,但不可能添加新部门或工作域) 我的搜索查询表如下所示: C

我在postgresql数据库中有两个表。表1=空缺,表2=搜索查询。我想根据用户之前的搜索查询向他们推荐职位空缺(只有最后10个搜索查询是重要的)

当用户搜索空缺时,他必须输入一些关键字,并且他可以选择一个位置(单个)、一个公司(单个)、多个部门(多个)、多个工作域(多个)和就业类型(多个)

行业和工作领域是关键,如“建筑”、“销售”、“技术”。就业类型、公司和地点是UUID,在其他表中有更多的规定(因为新公司可以加入,新地点可以加入,但不可能添加新部门或工作域)

我的搜索查询表如下所示:

CREATE TABLE search_queries(
  search_query_id uuid DEFAULT gen_random_uuid() NOT NULL,
  user_id uuid,
  keywords text[] NOT NULL,
  company_id uuid,
  location_id uuid,
  sectors text[],
  job_domains text[],
  employment_types uuid[]
);

--- EXAMPLE ROW
search_query_id = 9dde0eae-dfda-4e3d-9e87-55076111eee2;
user_id = 1d52fd2f-a830-4bf2-8249-e9cdf3681c3a;
keywords = {keyword1,keyword2};
location_id = NULL;
company_id = NULL;
sectors = {construction,sales};
job_domains = NULL;
employment_types = {0a1a702e-2f45-4c4d-b870-a41f83149835};
const keywordsArray = ['keyword1', 'keyword2', ...];
const locationIdArray = ['uuid1', ...];
const sectorsArray = ['construction', 'sales', ...];
// 1) join all keywords together
const keywordsQuery = `to_tosvector(title || ' ' || keywords) @@ to_tsquery('${keywordsArray.join(' | ')}')`;
// i'm using the | operator to search for 'OR' instead of 'AND' because not all keywords must be present in a vacancy to match.

// 2) create a postgresql array of all location ID's and check if a location ID exists in a vacancy.
// I only create the dynamic query part if the locationIdArray has values. If not, I just skip it.
const locationIdQuery = locationIdArray.length > 0 ? `OR location_id = ANY(ARRAY[${locationIdArray.join(',')}]::uuid[])` : '';

// 3) create a postgresql array of all sectors and check if a vacancy sector exists in the array
const sectorsQuery = sectorsArray.length > 0 ? `OR sector = ANY(ARRAY[${sectors.join(',')}])`: '';

// ... and so on for the other properties
const query = `
SELECT
    title,
    company,
    timestamp,
    (tsrank(to_tosvector(title || ' ' || keywords),to_tsquery('${keywordsArray.join(' | ')}'))::float AS relevance
FROM
    vacancies
WHERE
    ${keywordsQuery}
    ${locationIdQuery}
    ${sectorsQuery}
ORDER BY
    relevance DESC,
    timestamp DESC
`
在示例行中,用户搜索了“施工”和“销售”部门中的工作,工作类型为“临时”(UUID表示工作类型为临时),关键字为关键字1和关键字2

目前,当我想推荐作业时,我会做以下工作:获取用户的最后10个搜索查询,并将所有不同字段合并到数组中。我用最后10行中的所有关键字创建了一个关键字数组(我删除了重复项),我用所有位置ID创建了一个位置数组(我删除了重复项和空值)。。。等等然后我会得到这样的结果:

CREATE TABLE search_queries(
  search_query_id uuid DEFAULT gen_random_uuid() NOT NULL,
  user_id uuid,
  keywords text[] NOT NULL,
  company_id uuid,
  location_id uuid,
  sectors text[],
  job_domains text[],
  employment_types uuid[]
);

--- EXAMPLE ROW
search_query_id = 9dde0eae-dfda-4e3d-9e87-55076111eee2;
user_id = 1d52fd2f-a830-4bf2-8249-e9cdf3681c3a;
keywords = {keyword1,keyword2};
location_id = NULL;
company_id = NULL;
sectors = {construction,sales};
job_domains = NULL;
employment_types = {0a1a702e-2f45-4c4d-b870-a41f83149835};
const keywordsArray = ['keyword1', 'keyword2', ...];
const locationIdArray = ['uuid1', ...];
const sectorsArray = ['construction', 'sales', ...];
// 1) join all keywords together
const keywordsQuery = `to_tosvector(title || ' ' || keywords) @@ to_tsquery('${keywordsArray.join(' | ')}')`;
// i'm using the | operator to search for 'OR' instead of 'AND' because not all keywords must be present in a vacancy to match.

// 2) create a postgresql array of all location ID's and check if a location ID exists in a vacancy.
// I only create the dynamic query part if the locationIdArray has values. If not, I just skip it.
const locationIdQuery = locationIdArray.length > 0 ? `OR location_id = ANY(ARRAY[${locationIdArray.join(',')}]::uuid[])` : '';

// 3) create a postgresql array of all sectors and check if a vacancy sector exists in the array
const sectorsQuery = sectorsArray.length > 0 ? `OR sector = ANY(ARRAY[${sectors.join(',')}])`: '';

// ... and so on for the other properties
const query = `
SELECT
    title,
    company,
    timestamp,
    (tsrank(to_tosvector(title || ' ' || keywords),to_tsquery('${keywordsArray.join(' | ')}'))::float AS relevance
FROM
    vacancies
WHERE
    ${keywordsQuery}
    ${locationIdQuery}
    ${sectorsQuery}
ORDER BY
    relevance DESC,
    timestamp DESC
`
然后,我创建一个动态查询。我现在是这样做的:

CREATE TABLE search_queries(
  search_query_id uuid DEFAULT gen_random_uuid() NOT NULL,
  user_id uuid,
  keywords text[] NOT NULL,
  company_id uuid,
  location_id uuid,
  sectors text[],
  job_domains text[],
  employment_types uuid[]
);

--- EXAMPLE ROW
search_query_id = 9dde0eae-dfda-4e3d-9e87-55076111eee2;
user_id = 1d52fd2f-a830-4bf2-8249-e9cdf3681c3a;
keywords = {keyword1,keyword2};
location_id = NULL;
company_id = NULL;
sectors = {construction,sales};
job_domains = NULL;
employment_types = {0a1a702e-2f45-4c4d-b870-a41f83149835};
const keywordsArray = ['keyword1', 'keyword2', ...];
const locationIdArray = ['uuid1', ...];
const sectorsArray = ['construction', 'sales', ...];
// 1) join all keywords together
const keywordsQuery = `to_tosvector(title || ' ' || keywords) @@ to_tsquery('${keywordsArray.join(' | ')}')`;
// i'm using the | operator to search for 'OR' instead of 'AND' because not all keywords must be present in a vacancy to match.

// 2) create a postgresql array of all location ID's and check if a location ID exists in a vacancy.
// I only create the dynamic query part if the locationIdArray has values. If not, I just skip it.
const locationIdQuery = locationIdArray.length > 0 ? `OR location_id = ANY(ARRAY[${locationIdArray.join(',')}]::uuid[])` : '';

// 3) create a postgresql array of all sectors and check if a vacancy sector exists in the array
const sectorsQuery = sectorsArray.length > 0 ? `OR sector = ANY(ARRAY[${sectors.join(',')}])`: '';

// ... and so on for the other properties
const query = `
SELECT
    title,
    company,
    timestamp,
    (tsrank(to_tosvector(title || ' ' || keywords),to_tsquery('${keywordsArray.join(' | ')}'))::float AS relevance
FROM
    vacancies
WHERE
    ${keywordsQuery}
    ${locationIdQuery}
    ${sectorsQuery}
ORDER BY
    relevance DESC,
    timestamp DESC
`
我最终得到了这样一个查询:

CREATE TABLE search_queries(
  search_query_id uuid DEFAULT gen_random_uuid() NOT NULL,
  user_id uuid,
  keywords text[] NOT NULL,
  company_id uuid,
  location_id uuid,
  sectors text[],
  job_domains text[],
  employment_types uuid[]
);

--- EXAMPLE ROW
search_query_id = 9dde0eae-dfda-4e3d-9e87-55076111eee2;
user_id = 1d52fd2f-a830-4bf2-8249-e9cdf3681c3a;
keywords = {keyword1,keyword2};
location_id = NULL;
company_id = NULL;
sectors = {construction,sales};
job_domains = NULL;
employment_types = {0a1a702e-2f45-4c4d-b870-a41f83149835};
const keywordsArray = ['keyword1', 'keyword2', ...];
const locationIdArray = ['uuid1', ...];
const sectorsArray = ['construction', 'sales', ...];
// 1) join all keywords together
const keywordsQuery = `to_tosvector(title || ' ' || keywords) @@ to_tsquery('${keywordsArray.join(' | ')}')`;
// i'm using the | operator to search for 'OR' instead of 'AND' because not all keywords must be present in a vacancy to match.

// 2) create a postgresql array of all location ID's and check if a location ID exists in a vacancy.
// I only create the dynamic query part if the locationIdArray has values. If not, I just skip it.
const locationIdQuery = locationIdArray.length > 0 ? `OR location_id = ANY(ARRAY[${locationIdArray.join(',')}]::uuid[])` : '';

// 3) create a postgresql array of all sectors and check if a vacancy sector exists in the array
const sectorsQuery = sectorsArray.length > 0 ? `OR sector = ANY(ARRAY[${sectors.join(',')}])`: '';

// ... and so on for the other properties
const query = `
SELECT
    title,
    company,
    timestamp,
    (tsrank(to_tosvector(title || ' ' || keywords),to_tsquery('${keywordsArray.join(' | ')}'))::float AS relevance
FROM
    vacancies
WHERE
    ${keywordsQuery}
    ${locationIdQuery}
    ${sectorsQuery}
ORDER BY
    relevance DESC,
    timestamp DESC
`
此查询检查关键字存在的所有空缺或位置ID位于数组中的所有空缺 其中扇区位于数组中,结果根据相关性(和发布日期)排序

这是可行的,但我对这种方法有一些问题。

首先,它根据相关性对结果进行排序,但相关性仅基于关键词。我想订购“比赛”的结果。同时匹配关键字和位置ID的空缺在结果集中应高于仅匹配关键字的空缺

其次,我不知道这是否是正确的解决方案。目前,它是有效的,我将结果缓存在redis数据库中,因此这种“计算”不是每次用户刷新页面时都进行的,而是每小时进行一次

有人能帮我解决这个问题吗?其他人如何根据另一个表中的行“建议”内容?这是正确的方式,还是我在监督什么