fix(graph): resolve cited_id to papers.id via openalex_id JOIN
build_citation_graph now does: SELECT c.citing_id, COALESCE(p.id, c.cited_id) AS cited_id FROM citations c LEFT JOIN papers p ON p.openalex_id = c.cited_id Before: cited_id (OpenAlex IDs) never matched papers.id (DOIs) → 13 cross-citations between ingested papers were invisible in graph. After: in-KB papers use their canonical DOI key; dangling references keep their raw OpenAlex ID unchanged. Test: test_cross_citation_uses_doi_when_in_kb (42 passed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,11 @@ def build_citation_graph(conn: Any) -> nx.DiGraph:
|
||||
the citing paper references the cited paper. Both ingested papers
|
||||
and dangling targets (cited but not yet ingested) appear as nodes.
|
||||
|
||||
``cited_id`` in the citations table stores OpenAlex IDs; ``papers.id``
|
||||
stores DOIs. A LEFT JOIN resolves cited papers that are in the KB to
|
||||
their canonical DOI key via ``papers.openalex_id``. Dangling references
|
||||
(not in KB) keep their raw OpenAlex ID.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
conn:
|
||||
@@ -40,7 +45,13 @@ def build_citation_graph(conn: Any) -> nx.DiGraph:
|
||||
-------
|
||||
nx.DiGraph with every (citing_id, cited_id) pair as an edge.
|
||||
"""
|
||||
rows = conn.execute("SELECT citing_id, cited_id FROM citations").fetchall()
|
||||
rows = conn.execute(
|
||||
"""
|
||||
SELECT c.citing_id, COALESCE(p.id, c.cited_id) AS cited_id
|
||||
FROM citations c
|
||||
LEFT JOIN papers p ON p.openalex_id = c.cited_id
|
||||
"""
|
||||
).fetchall()
|
||||
g: nx.DiGraph = nx.DiGraph()
|
||||
for row in rows:
|
||||
g.add_edge(row["citing_id"], row["cited_id"])
|
||||
|
||||
@@ -80,6 +80,24 @@ class TestBuildCitationGraph:
|
||||
g = build_citation_graph(_make_conn(rows))
|
||||
assert "not_in_papers" in g.nodes()
|
||||
|
||||
def test_cross_citation_uses_doi_when_in_kb(self):
|
||||
# Simulate DB COALESCE: cited_id already resolved to papers.id (DOI)
|
||||
# for in-KB papers; dangling references keep their OpenAlex ID.
|
||||
rows = [
|
||||
{
|
||||
"citing_id": "https://doi.org/10.1234/paper-a",
|
||||
"cited_id": "https://doi.org/10.5678/paper-b",
|
||||
},
|
||||
{
|
||||
"citing_id": "https://doi.org/10.5678/paper-b",
|
||||
"cited_id": "https://openalex.org/W999",
|
||||
},
|
||||
]
|
||||
g = build_citation_graph(_make_conn(rows))
|
||||
assert g.has_edge("https://doi.org/10.1234/paper-a", "https://doi.org/10.5678/paper-b")
|
||||
assert g.has_edge("https://doi.org/10.5678/paper-b", "https://openalex.org/W999")
|
||||
assert g.number_of_nodes() == 3
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# citation_pagerank
|
||||
|
||||
Reference in New Issue
Block a user