76 lines
5.4 KiB
Python
76 lines
5.4 KiB
Python
"""Read-only command-line queries for the paper index."""
|
|
import argparse
|
|
import json
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--db', required=True)
|
|
parser.add_argument('--query', help='SQLite FTS5 query over title and abstract')
|
|
parser.add_argument('--paper',type=int,help='Paper ID; include sources, tags and submission history')
|
|
parser.add_argument('--tag', help='Filter as namespace=value, e.g. arxiv:category=cs.AI')
|
|
parser.add_argument('--venue', help='Conference acronym')
|
|
parser.add_argument('--year', type=int)
|
|
parser.add_argument('--track',help='Exact track, e.g. main, findings, workshop')
|
|
parser.add_argument('--status', choices=['accepted','rejected','desk_rejected','withdrawn','under_review','unknown'])
|
|
parser.add_argument('--limit', type=int, default=20)
|
|
parser.add_argument('--stats', action='store_true')
|
|
args = parser.parse_args()
|
|
conn = sqlite3.connect(Path(args.db).resolve().as_uri()+'?mode=ro', uri=True)
|
|
conn.row_factory = sqlite3.Row
|
|
conn.execute('BEGIN') # One consistent read snapshot while ingestion continues.
|
|
if args.stats:
|
|
result = {name:conn.execute('SELECT count(*) FROM '+name).fetchone()[0] for name in ('papers','source_records','submissions','decisions','tags','match_candidates')}
|
|
result['records_by_source'] = [dict(r) for r in conn.execute('SELECT s.name,count(r.id) AS imported_records FROM sources s LEFT JOIN source_records r ON r.source_id=s.id GROUP BY s.id ORDER BY s.name')]
|
|
result['decision_events_by_status'] = [dict(r) for r in conn.execute('SELECT status,count(*) AS events FROM decisions GROUP BY status')]
|
|
result['coverage'] = [dict(r) for r in conn.execute('SELECT status,count(*) AS sources FROM edition_sources GROUP BY status')]
|
|
result['runs'] = [dict(r) for r in conn.execute('SELECT * FROM ingest_runs ORDER BY id DESC LIMIT 10')]
|
|
else:
|
|
where = []; params = []
|
|
if args.paper is not None:
|
|
where.append('p.id=?'); params.append(args.paper)
|
|
if args.query:
|
|
where.append('p.id IN (SELECT rowid FROM papers_fts WHERE papers_fts MATCH ?)'); params.append(args.query)
|
|
if args.tag:
|
|
namespace,value = args.tag.split('=',1)
|
|
where.append('EXISTS(SELECT 1 FROM paper_tags pt JOIN tags t ON t.id=pt.tag_id WHERE pt.paper_id=p.id AND t.namespace=? AND t.value=?)'); params.extend([namespace,value])
|
|
if args.venue or args.year or args.status or args.track:
|
|
clause = ['1=1']
|
|
if args.venue:
|
|
if conn.execute("SELECT 1 FROM sqlite_master WHERE type='table' AND name='venue_aliases'").fetchone():
|
|
clause.append('(v.acronym=? COLLATE NOCASE OR EXISTS(SELECT 1 FROM venue_aliases va WHERE va.venue_id=v.id AND va.alias=? COLLATE NOCASE))'); params.extend([args.venue,args.venue])
|
|
else:
|
|
clause.append('v.acronym=? COLLATE NOCASE');params.append(args.venue)
|
|
if args.track:
|
|
clause.append('e.track=?');params.append(args.track)
|
|
if args.year:
|
|
clause.append('e.year=?'); params.append(args.year)
|
|
if args.status:
|
|
clause.append('EXISTS(SELECT 1 FROM decisions d WHERE d.submission_id=s.id AND d.status=? AND NOT EXISTS(SELECT 1 FROM decisions newer WHERE newer.submission_id=d.submission_id AND (newer.observed_at>d.observed_at OR (newer.observed_at=d.observed_at AND newer.id>d.id))))'); params.append(args.status)
|
|
where.append('p.id IN (SELECT s.paper_id FROM submissions s JOIN editions e ON e.id=s.edition_id JOIN venues v ON v.id=e.venue_id WHERE '+' AND '.join(clause)+')')
|
|
sql = 'SELECT p.* FROM papers p'+(' WHERE '+' AND '.join(where) if where else '')+' ORDER BY p.id LIMIT ?'
|
|
params.append(max(1,min(args.limit,200)))
|
|
result = []
|
|
for row in conn.execute(sql,params):
|
|
paper = dict(row)
|
|
paper['authors'] = json.loads(paper.pop('authors_json'))
|
|
paper['identifiers'] = [dict(r) for r in conn.execute('SELECT scheme,value FROM identifiers WHERE paper_id=?',(row['id'],))]
|
|
if args.paper is not None:
|
|
paper['tags'] = [dict(r) for r in conn.execute('SELECT t.namespace,t.value,pt.evidence_key FROM paper_tags pt JOIN tags t ON t.id=pt.tag_id WHERE pt.paper_id=?',(row['id'],))]
|
|
paper['sources'] = [dict(r) for r in conn.execute('SELECT s.name,r.external_id,r.url,r.title,r.abstract,r.retrieved_at FROM source_records r JOIN sources s ON s.id=r.source_id WHERE r.paper_id=?',(row['id'],))]
|
|
submissions = []
|
|
for sub in conn.execute('SELECT s.id,s.source_submission_id,s.submitted_at,v.acronym,e.year,e.track FROM submissions s JOIN editions e ON e.id=s.edition_id JOIN venues v ON v.id=e.venue_id WHERE s.paper_id=? ORDER BY e.year,s.id',(row['id'],)):
|
|
submission = dict(sub)
|
|
submission['decisions'] = [dict(d) for d in conn.execute('SELECT status,raw_value,evidence_url,observed_at,decision_date FROM decisions WHERE submission_id=? ORDER BY observed_at,id',(sub['id'],))]
|
|
submissions.append(submission)
|
|
paper['submissions'] = submissions
|
|
result.append(paper)
|
|
print(json.dumps(result,ensure_ascii=False,indent=2))
|
|
conn.close()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|