简体   繁体   中英

Bigquery matching words counts between two tables

given these two tables ( documents and labels ) how can I find match counts for all the label's pattern s from the labels table, found in the document field of documents table (count exact matches, using regex is optional)

WITH documents  AS (
  SELECT 1 AS id, "foo bar, foo baz" AS document UNION ALL
  SELECT 2, "foo bar bar qux" UNION ALL
  SELECT 3, "etc blah blah"
),

labels as (
  select 'FOO_LABEL' as label, 'foo' as pattern UNION ALL
  select 'FOO_LABEL', 'qux' UNION ALL
  select 'BAR_LABEL', 'bar' UNION ALL
  select 'ETC_LABEL', 'etc'
)

the expected matches counts by document:

id, label, cnt
1,  FOO_LABEL, 2
1,  BAR_LABEL, 1
2,  FOO_LABEL, 2
2,  BAR_LABEL, 2
3,  ETC_LABEL, 1

the difference from this question is that I need actual match counts

and unlike this question my patterns are coming from a separate table

there are ~100M documents, and ~1000 rows in labels table

Consider below approach

select id, label, count(*) cnt
from documents, unnest(regexp_extract_all(document, r'[\w]+')) pattern
join labels
using(pattern)
group by id, label       

if applied to sample data in your question - output is

在此处输入图像描述

Mikhail Berlyant 's answer above is perfect, I just realized I needed substring match instead of exact word match, so i slightly modified it by replacing using(pattern) with ON STRPOS(word, pattern)>0 in the JOIN :

WITH documents  AS (
  SELECT 1 AS id, "foo bar foobar qux" AS document UNION ALL
  SELECT 2, "foooooo barbar"
),

labels as (
  select 'FOO_LABEL' as label, 'foo' as pattern UNION ALL
  select 'FOO_LABEL', 'qux' UNION ALL
  select 'BAR_LABEL', 'bar' 
)

select id, label, count(*) cnt
from documents, unnest(regexp_extract_all(document, r'[\w]+')) word
join labels
ON STRPOS(word, pattern)>0 --faster that regexp_contains(word, pattern)
group by id, label 

在此处输入图像描述

Edit : another minor change to work with phrases/sentences instead of matching individual words (the doc is split into phrases delimited by commas, etc), so that it works for multi-word patterns . this misses some counts (ie repeated substring matches within phrase) but faster overall

WITH documents  AS (
  SELECT 1 AS id, "foo 123 test foo 123" AS document UNION ALL
  SELECT 2, "all bars, all bars all bars "
),

labels as (
  select 'FOO_LABEL' as label, 'foo 123' as pattern UNION ALL
  select 'BAR_LABEL', 'all bar' 
)

select id, label, count(*) cnt
from documents, UNNEST(REGEXP_EXTRACT_ALL(document , r'([^.!;(),\n~|]+)')) AS phrase
join labels
ON STRPOS(phrase, pattern)>0 
group by id, label 

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM