Skip to content

Commit

Permalink
advanced search: unlock full potential of $contains operator (#1248)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstucke authored Nov 26, 2024
1 parent 28035d0 commit 42f7320
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/storage/query_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def _get_array_filter(field, key, value):
column = func.array_to_string(field, ',')
return _dict_key_to_filter(column, key, value)
if '$contains' in value:
return field.contains(_to_list(value['$contains']))
return field.contains(value['$contains'])
if '$overlap' in value:
return field.overlap(_to_list(value['$overlap']))
raise QueryConversionException(f'Unsupported search option for ARRAY field: {value}')
Expand Down
19 changes: 17 additions & 2 deletions src/test/integration/storage/test_db_interface_frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def test_generic_search_nested(frontend_db, backend_db):
assert frontend_db.generic_search({'processed_analysis.plugin.nested_2.inner_nested.test': 3}) == [fo.uid]


def test_generic_search_json_array(frontend_db, backend_db):
def test_generic_search_list_contains(frontend_db, backend_db):
fo, fw = create_fw_with_child_fo()
fo.processed_analysis = {'plugin': generate_analysis_entry(analysis_result={'list': ['a', 'b']})}
fw.processed_analysis = {'plugin': generate_analysis_entry(analysis_result={'list': ['b', 'c']})}
Expand All @@ -240,6 +240,21 @@ def test_generic_search_json_array(frontend_db, backend_db):
assert frontend_db.generic_search({'processed_analysis.plugin.list': {'$contains': 'd'}}) == []


def test_generic_search_dict_contains(frontend_db, backend_db):
fo, fw = create_fw_with_child_fo()
fo.processed_analysis = {'plugin': generate_analysis_entry(analysis_result={'list': {'a': 1, 'b': 2}})}
fw.processed_analysis = {'plugin': generate_analysis_entry(analysis_result={'list': {'b': 2, 'c': 3}})}
backend_db.insert_object(fw)
backend_db.insert_object(fo)

assert frontend_db.generic_search({'processed_analysis.plugin.list': {'$contains': {'a': 1}}}) == [fo.uid]
assert set(frontend_db.generic_search({'processed_analysis.plugin.list': {'$contains': {'b': 2}}})) == {
fo.uid,
fw.uid,
}
assert frontend_db.generic_search({'processed_analysis.plugin.list': {'$contains': {'a': 2}}}) == []


def test_generic_search_dict_in_list(backend_db, frontend_db):
fw, parent_fo, child_fo = create_fw_with_parent_and_child()
parent_fo.processed_analysis = {
Expand Down Expand Up @@ -323,7 +338,7 @@ def test_generic_search_tags(frontend_db, backend_db):
assert frontend_db.generic_search({'firmware_tags': 'bar'}) == ['fw_1']
assert frontend_db.generic_search({'firmware_tags': 'test'}) == ['fw_2']
assert sorted(frontend_db.generic_search({'firmware_tags': 'foo'})) == ['fw_1', 'fw_2']
assert sorted(frontend_db.generic_search({'firmware_tags': {'$contains': 'foo'}})) == ['fw_1', 'fw_2']
assert sorted(frontend_db.generic_search({'firmware_tags': {'$contains': ['foo']}})) == ['fw_1', 'fw_2']
assert sorted(frontend_db.generic_search({'firmware_tags': {'$overlap': ['bar', 'test']}})) == ['fw_1', 'fw_2']
assert frontend_db.generic_search({'firmware_tags': {'$overlap': ['none']}}) == []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ <h4>Example queries:</h4>
</p>
<p>
Check if array contains value (JSON columns only): <kbd>"$contains"</kbd><br />
<span class="example-json">{"processed_analysis.software_components.OpenSSL.meta.version": {"$contains": "1.0.1f"}}</span><br />
<span class="example-json">{"processed_analysis.software_components.OpenSSL.meta.version": {"$contains": ["1.0.1f"]}}</span><br />
<span class="example-comment">Select files where OpenSSL version 1.0.1f was found</span>
</p>

Expand Down

0 comments on commit 42f7320

Please sign in to comment.