|
19 | 19 | {'name': 'name', 'type': 'string', 'optional': True}, |
20 | 20 | {'name': 'description', 'type': 'string', 'optional': True}, |
21 | 21 | {'name': 'type', 'type': 'string', 'optional': True, 'facet': True}, |
22 | | - {'name': 'role', 'type': 'string', 'optional': True}, |
23 | | - {'name': 'sboltype', 'type': 'string', 'optional': True}, |
| 22 | + {'name': 'role', 'type': 'string', 'optional': True, 'facet': True}, |
| 23 | + {'name': 'sboltype', 'type': 'string', 'optional': True, 'facet': True}, |
24 | 24 | {'name': 'keywords', 'type': 'string', 'optional': True}, |
25 | 25 | {'name': 'graph', 'type': 'string', 'facet': True}, |
26 | 26 | {'name': 'pagerank', 'type': 'float'}, |
@@ -51,6 +51,42 @@ def create_parts_collection(collection_name): |
51 | 51 | logger_.log('Collection created', True) |
52 | 52 |
|
53 | 53 |
|
| 54 | +def upsert_synonyms(collection_name): |
| 55 | + """ |
| 56 | + Registers curated search synonyms (domain abbreviations, e.g. lac<->lacI, |
| 57 | + rfp<->mRFP1, "ribosome binding site"<->rbs) on the collection. |
| 58 | +
|
| 59 | + Synonyms are COLLECTION-SCOPED, so create_parts_collection() wipes them every |
| 60 | + time it recreates the collection -- this MUST run on every reindex or the |
| 61 | + recall fixes silently disappear. The list lives in synonyms.json (curated |
| 62 | + separately from code); each entry is {"id", "synonyms": [...]} for a |
| 63 | + multi-way set, optionally with "root" for a one-way expansion. |
| 64 | +
|
| 65 | + Missing/empty synonyms.json is non-fatal: indexing proceeds without synonyms. |
| 66 | + """ |
| 67 | + try: |
| 68 | + with open('synonyms.json', 'r') as f: |
| 69 | + synonym_sets = json.load(f) |
| 70 | + except FileNotFoundError: |
| 71 | + logger_.log('No synonyms.json found -> skipping synonyms', True) |
| 72 | + return |
| 73 | + |
| 74 | + collection = typesense_manager.get_client().collections[collection_name] |
| 75 | + |
| 76 | + # Clear existing synonyms first so the collection matches synonyms.json |
| 77 | + # exactly -- keeps this idempotent even when called standalone (not via a |
| 78 | + # full reindex, which would already recreate the collection from scratch). |
| 79 | + for existing in collection.synonyms.retrieve().get('synonyms', []): |
| 80 | + collection.synonyms[existing['id']].delete() |
| 81 | + |
| 82 | + for entry in synonym_sets: |
| 83 | + body = {'synonyms': entry['synonyms']} |
| 84 | + if entry.get('root'): |
| 85 | + body['root'] = entry['root'] |
| 86 | + collection.synonyms.upsert(entry['id'], body) |
| 87 | + logger_.log(f'Registered {len(synonym_sets)} synonym set(s)', True) |
| 88 | + |
| 89 | + |
54 | 90 | def add_pagerank(parts_response, uri2rank): |
55 | 91 | """ |
56 | 92 | Adds the pagerank score for each part. |
@@ -153,6 +189,7 @@ def update_index(uri2rank): |
153 | 189 | add_sbol_type(parts_response) |
154 | 190 | create_parts_collection(collection_name) |
155 | 191 | bulk_index_parts(parts_response, collection_name) |
| 192 | + upsert_synonyms(collection_name) |
156 | 193 |
|
157 | 194 | logger_.log(f'******** Finished adding {len(parts_response)} parts to index ********', True) |
158 | 195 | logger_.log('------------ Successfully updated index ------------\n', True) |
|
0 commit comments