Skip to content

Commit

Permalink
moderation:added cli command to add queries
Browse files Browse the repository at this point in the history
  • Loading branch information
0einstein0 committed Nov 8, 2024
1 parent 7829b58 commit 7729454
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 20 deletions.
12 changes: 7 additions & 5 deletions site/tests/moderation/test_moderation_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
"""Test ModerationQuery model class."""

from invenio_db import db
from invenio_search import current_search_client
from zenodo_rdm.moderation.models import ModerationQuery
from zenodo_rdm.moderation.rules import match_query_rule
from zenodo_rdm.api import ZenodoRDMRecord


def test_moderation_query_creation(app):
"""Test to create and index a ModerationQuery."""
Expand All @@ -22,7 +20,10 @@ def test_moderation_query_creation(app):
active = True

query = ModerationQuery.create(
query_string, ZenodoRDMRecord, notes=notes, score=score, active=active
query_string,
notes=notes,
score=score,
active=active,
)
db.session.commit()

Expand All @@ -36,4 +37,5 @@ def test_moderation_query_creation(app):
]
)

#TODO: Add test for matching query

# TODO: Add test for matching query
82 changes: 82 additions & 0 deletions site/zenodo_rdm/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# ZenodoRDM is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
"""Zenodo RDM cli commands."""
import csv
import os

import click
from flask.cli import with_appcontext
Expand All @@ -27,9 +29,11 @@
from invenio_requests.records.models import RequestMetadata

from zenodo_rdm.api import ZenodoRDMRecord
from zenodo_rdm.moderation.models import ModerationQuery
from zenodo_rdm.moderation.percolator import (
create_percolator_index,
get_percolator_index,
index_percolate_query,
)


Expand Down Expand Up @@ -279,3 +283,81 @@ def create_index(record_cls):
click.secho(f"Percolator index '{index_name}' created successfully.")
except Exception as e:
click.secho(f"Error creating percolator index: {e}")


@moderation.command("add-query")
@click.option(
"-r",
"--record-cls",
type=click.Choice(["records", "communities"], case_sensitive=False),
default="records",
help="Record class to base the query on (default: records).",
)
@click.option(
"-q",
"--query-string",
help="The query string for the moderation query (optional if loading from CSV).",
)
@click.option(
"-n",
"--notes",
default="Example note",
help="Additional notes for the moderation query (optional if loading from CSV).",
)
@click.option(
"-s",
"--score",
default=10,
type=int,
help="The score for the moderation query (optional if loading from CSV).",
)
@click.option(
"-a",
"--active",
default=True,
type=bool,
help="Whether the query is active (optional if loading from CSV).",
)
@click.option(
"-f",
"--file",
type=click.Path(exists=True, readable=True),
help="Path to CSV file containing queries.",
)
@with_appcontext
def add_query(record_cls, query_string, notes, score, active, file):
"""Command to add a moderation query from CSV or directly and index it."""
record_cls = ZenodoRDMRecord if record_cls == "records" else Community

try:
if file:
add_queries_from_csv(file, record_cls)
else:
create_and_index_query(record_cls, query_string, notes, score, active)

click.secho("Queries added and indexed successfully.")
except Exception as e:
click.secho(f"Error adding or indexing query: {e}")


def add_queries_from_csv(
file_path, record_cls=ZenodoRDMRecord, notes=None, score=10, active=True
):
"""Load queries from a CSV file, add them to the database, and index them."""
with open(file_path, mode="r", newline="", encoding="utf-8") as csvfile:
csvreader = csv.reader(csvfile)

for row in csvreader:
if row:
query_string = row[0].strip().strip("'")
create_and_index_query(record_cls, query_string, notes, score, active)


def create_and_index_query(record_cls, query_string, notes, score, active):
"""Create and index a single moderation query."""
query = ModerationQuery.create(
query_string=query_string, notes=notes, score=score, active=active
)

db.session.commit()
index_percolate_query(record_cls, query.id, query_string, active, score, notes)
1 change: 1 addition & 0 deletions site/zenodo_rdm/moderation/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

MODERATION_PERCOLATOR_MAPPING = {
"properties": {
"id": {"type": "keyword"},
"query": {"type": "percolator"},
"score": {"type": "integer"},
"notes": {"type": "text"},
Expand Down
17 changes: 3 additions & 14 deletions site/zenodo_rdm/moderation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
from invenio_search import current_search_client
from sqlalchemy_utils import ChoiceType, Timestamp

from zenodo_rdm.api import ZenodoRDMRecord

from .percolator import index_percolate_query


class LinkDomainStatus(enum.Enum):
"""Link domain status."""
Expand Down Expand Up @@ -86,7 +82,7 @@ class ModerationQuery(db.Model):

__tablename__ = "moderation_queries"

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
id = db.Column(db.Integer, primary_key=True)
"""Primary key identifier for the moderation query."""

score = db.Column(db.Integer, default=0)
Expand All @@ -102,26 +98,19 @@ class ModerationQuery(db.Model):
"""Indicates whether the moderation query is currently active."""

@classmethod
def create(
cls, query_string, record_cls=ZenodoRDMRecord, notes=None, score=0, active=True
):
def create(cls, query_string, notes=None, score=0, active=True):
"""Create a new moderation query with a configurable record class."""
query = cls(query_string=query_string, notes=notes, score=score, active=active)
db.session.add(query)

index_percolate_query(record_cls, query_string, active, score, notes)

return query

@classmethod
def get(cls, query_id=None):
"""Retrieve a moderation query by ID or return all queries if no ID is provided."""
if query_id is not None:
return cls.query.filter_by(id=query_id).one_or_none()
return cls.query.all()

def __repr__(self):
"""Get a string representation of the moderation query."""
return (
f"<ModerationQuery id={self.id}, score={self.score}, active={self.active}>"
)
return f"<ModerationQuery id={self.id}, query_string={self.query_string}, score={self.score}, active={self.active}>"
5 changes: 4 additions & 1 deletion site/zenodo_rdm/moderation/percolator.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ def create_percolator_index(record_cls):
current_app.logger.exception(e)


def index_percolate_query(record_cls, query_string, active=True, score=1, notes=None):
def index_percolate_query(
record_cls, query_id, query_string, active=True, score=1, notes=None
):
"""Index a percolate query."""
try:
current_search_client.index(
index=get_percolator_index(record_cls),
body={
"id": query_id,
"query": {"query_string": {"query": query_string}},
"active": active,
"score": score,
Expand Down

0 comments on commit 7729454

Please sign in to comment.