feat: Generate stores taxonomy from name-suggestion-index - #9607
feat: Generate stores taxonomy from name-suggestion-index#9607CloCkWeRX wants to merge 27 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9607 +/- ##
==========================================
+ Coverage 50.30% 55.49% +5.18%
==========================================
Files 103 104 +1
Lines 26398 26456 +58
Branches 6315 6324 +9
==========================================
+ Hits 13280 14681 +1401
+ Misses 11357 9850 -1507
- Partials 1761 1925 +164
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
|
@teolemon can you review this PR ? I personally lack context to understand. |
|
cc @raphodn |
teolemon
left a comment
There was a problem hiding this comment.
It looks really nice to me, I just required a review from the 2 Raphael from Open Prices, since this will potentially be really helpful for them.
What was your personal intent behind this PR ?
It's not really a superseed of it, as we currently have no way of knowing whether a specific store belongs to a bigger chain. Basically, on Open Prices, I would like to have a new table that could be named something like I will open a new discussion on Open Prices repo to discuss the matter. edit: Done here: openfoodfacts/open-prices#863 |
There was a problem hiding this comment.
I wouldn't restrict to just shop/supermarket.json
- OFF:
shop/convenience,shop/alcohol,shop/wine,shop/bakery... - OBF:
shop/beauty - OPF:
shop/doityourself,shop/toys,shop/sports,shop/books... - OPFF:
shop/pet
There was a problem hiding this comment.
So, can do that, would the preference be 1x script per topic; or all in one?
There was a problem hiding this comment.
all in one ? 😁
with a nsi_kv: shop/convenience ?
There was a problem hiding this comment.
Definitely all in one. It would lead to a lot of duplication (or complication) if store-brands had to be repeated for each OxF type they were applicable for (e.g., most supermarkets/grocery or general stores/etc. would fit in all of them).
There was a problem hiding this comment.
I'm a big fan of the idea of leveraging NSI 👍
fyi I'm regularly contributing to the project, see openfoodfacts/open-prices#467 (comment)
There was a problem hiding this comment.
Maybe store a nsi_id: carrefour-c622af to know that it comes from NSI ?
- to easily find it back
- and differentiate in the taxonomy shops coming from NSI from shops coming from OFF contributors ?
- thus knowing which shops could be added back to NSI
There was a problem hiding this comment.
Happy to split these out into an stores-nsi.txt or something of that nature to more clearly split it; I feel like at the time I did this manually.
Script likely needs to be re-run since it's been ~2 years.
There was a problem hiding this comment.
I can have a look later this week and try to re-run the script myself.
if we switch to xx: then the country mapping could be removed ?
There was a problem hiding this comment.
if we switch to
xx:then the country mapping could be removed ?
I think country mapping could still be useful, esp. for cases where store-brands may have identical or near-identical names in different regions (see e.g. the 50 or so “COOP”s). (Mappings like country:en: en:United States of America,en:United States of America,en:United States of America,en:United States of America,en:United States of America are probably a bit excessive though…). Maybe this is too much “preemptive optimisation(/complication)” though, and could be easily solved with a human-added comment:en: key or similar where it’s actually needed.
Definitely +1 to using xx: similar to our brands.txt taxonomy though, with possible locale specific overrides for locales with scripts other than the first/primary xx: alias where relevant.
|
|
Let us go ahead with this and readjust later. |
|
@raphodn @CloCkWeRX @aleene @Freso @raphael0202 Should I do as suggested by @aleene , approving and merging ? Otherwise, can someone else do so ? |
|
|
I’m fine with whatever! |
teolemon
left a comment
There was a problem hiding this comment.
Approving this one since it's peripheral and useful
| wikidata:en:Q483551 | ||
| country:en: en:China | ||
|
|
||
| 117.1140042,36.6507007,50:济南华联超市 |
There was a problem hiding this comment.
Pull request overview
This PR adds a large snapshot of Name Suggestion Index (NSI) “shop/supermarket” brands into the stores.txt taxonomy format (plus a small amount of Wikidata enrichment for existing entries) and introduces a Node.js helper script intended to (re)generate that snapshot from NSI JSON.
Changes:
- Extend
taxonomies/unused/stores.txtwith ~3.5k NSI-derived store entries and add a few missingwikidata:*properties for existing stores. - Add
taxonomies/external/name-suggestion-index/shop/supermarket.jsto transform NSI JSON intostores.txt-style blocks. - Update
.github/labeler.ymlso NSI taxonomy generator files are labeled as “Stores” changes.
Reviewed changes
Copilot reviewed 2 out of 4 changed files in this pull request and generated 9 comments.
| File | Description |
|---|---|
| taxonomies/unused/stores.txt | Adds NSI-derived store taxonomy snapshot and some Wikidata properties; currently includes malformed entry headers that will be ignored by the taxonomy parser. |
| taxonomies/external/name-suggestion-index/shop/supermarket.js | Adds a generator script; currently mishandles non-ISO locationSet.include values, producing invalid stores.txt entry headers. |
| .github/labeler.yml | Expands Stores labeler globs to include the new NSI generator directory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Do not use results without careful review | ||
| const data = require('./supermarket.json'); | ||
|
|
||
| // A quick ISO 3601 to human labels (english) mapping. |
| data["items"].forEach(function (record) { | ||
| var countryCodes = record.locationSet["include"]; | ||
| var countryNames = []; | ||
| countryCodes.forEach(function (code) { | ||
| if (code == "001") { return; } | ||
|
|
||
| if (!iso3601[code.toString().split("-")[0]]) { | ||
| // console.debug("Unmapped ISO3601 code: " + code); | ||
| return; | ||
| } else { | ||
| countryNames.push("en:" + iso3601[code.toString().split("-")[0]]); | ||
| } | ||
| }); | ||
|
|
||
| var primaryCountryCode = countryCodes[0].toString().split("-")[0]; | ||
| var primaryLanguageCode = primaryCountryCode; | ||
| if (iso3601_to_language_mappings[primaryCountryCode]) { | ||
| primaryLanguageCode = iso3601_to_language_mappings[primaryCountryCode] | ||
| } | ||
|
|
| 001:Amazon Fresh | ||
| wikidata:en:Q4740834 | ||
|
|
| foodland_eastern_us.geojson:FoodLand (USA) | ||
| wikidata:en:Q5465271 | ||
|
|
| :masymas (Hijos de Luis Rodríguez) | ||
| wikidata:en:Q6135987 | ||
|
|
| :masymas (Juan Fornés Fornés) | ||
| wikidata:en:Q6135987 | ||
|
|
| :masymas (Luis Piña) | ||
| wikidata:en:Q6135987 | ||
|
|
| 117.1140042,36.6507007,50:东方冷库 | ||
| wikidata:en:Q123025086 | ||
|
|
| 117.1140042,36.6507007,50:济南华联超市 | ||
| wikidata:en:Q123025079 | ||
|
|
…permarket data processing
…egeneration Merge origin/main into feature/7632-stores-taxinomy. The only conflicted path was taxonomies/unused/stores.txt; everything else merged cleanly and is staged as-is. Reasoning per side: - origin/main touched taxonomies/unused/stores.txt with whitespace-only changes: it collapsed duplicated consecutive blank lines inside the hand-written section of the taxonomy. A diff between the merge base (a4879ce) and main shows exclusively deletions of empty lines, no additions or modifications of content lines, so there was no semantic change from main to reconcile. - This PR branch (HEAD) made two kinds of changes to the same file, which must both be preserved because the file was partly regenerated from the name-suggestion-index (NSI) dataset in this branch: 1. Added missing "wikidata:en:" identifiers to existing hand-written entries (Bio C' Bon Q54312551, Hyper U / U Express / Super U Q2529029, La vie claire Q3213589, Delhaize Q1184173, Colruyt Q2363991). 2. Appended the large "# Stores via name-suggestion-index" block at the end of the file, generated from data/brands/shop/supermarket.json at NSI commit a86dd15d303126f8cfc7831aa395ba3d3546fb10 (~4k store entries with Wikidata IDs and country coverage). Resolution applied: - Kept the entire NSI-generated block from HEAD verbatim. Since it was regenerated in this PR from the pinned NSI snapshot, re-editing it by hand would desynchronize it from its source; main contained nothing in that region anyway. - Kept main's blank-line normalization in the hand-written top section, so the file stays tidy where git auto-merged both sides already. - Removed only the three conflict marker lines ("<<<<<<< HEAD", "=======", ">>>>>>> main"); no entry, property or country line was altered beyond that. Resulting file = PR branch content + main's whitespace cleanup, i.e. the union of both sides without losing anything from either. Merge conflict resolved by Ox Alpha Free (Unlimited), running via OpenCode Zen. Co-authored-by: hangy <hangy@hangy.de>
|
| } | ||
|
|
||
| // Overrides for the language codes/mappings inferred by country code. | ||
| // TODO: This list is far, far from accurate or complete and should be replaced with any internal/authoritative mappings |
There was a problem hiding this comment.
Would it be possible to use the language property from the countries taxonomy?
|
|
||
| // A quick ISO 3601 to human labels (english) mapping. | ||
| // TODO: Ensure this matches exactly with countries.txt | ||
| // TODO: Replace with a better lookup |
There was a problem hiding this comment.
Could this utilise the countries taxonomy?



Fixes #7632 ?
What
This adds a snapshot of the BSD 3 clause licenced name-suggestion-index records for shop/supermarket, transformed into a stores.txt taxinomy format.
There may be some mapping inconsistencies with countries.txt, as I used ISO3601 2 letter codes and added 1 or 2 minor adjustments.
While I added this as a snapshot in git, it would be trivial to fetch the live data from upstream.
Running/generating:
What should be done to make this better