-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
scripts: added script to move records and communities in bulk.
- Loading branch information
1 parent
8b95e61
commit a99e7c4
Showing
1 changed file
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Copyright (C) 2024 CERN. | ||
# | ||
# Zenodo-RDM is free software; you can redistribute it and/or modify | ||
# it under the terms of the MIT License; see LICENSE file for more details. | ||
"""Script to transfer communities and records to new parent.""" | ||
|
||
from invenio_communities.proxies import current_communities | ||
from invenio_rdm_records.proxies import current_rdm_records | ||
from invenio_records_resources.services.uow import UnitOfWork | ||
from invenio_search.engine import dsl | ||
from werkzeug.local import LocalProxy | ||
|
||
community_service = LocalProxy(lambda: current_communities.service) | ||
records_communities_service = LocalProxy( | ||
lambda: current_rdm_records.record_communities_service | ||
) | ||
records_service = LocalProxy(lambda: current_rdm_records.records_service) | ||
|
||
|
||
def _all_records_q(community_ids): | ||
"""Auxiliary function that creates a query to filter records by community ids. | ||
Fetches the latest versions of the records only. | ||
:param community_ids: The list of community ids to filter the records by. | ||
""" | ||
extra_filter = dsl.query.Bool( | ||
"must", | ||
must=[ | ||
dsl.Q("terms", **{"parent.communities.ids": community_ids}), | ||
dsl.Q("term", **{"versions.is_latest": True}), | ||
], | ||
) | ||
|
||
return extra_filter | ||
|
||
|
||
def _search_records(identity, records_q): | ||
"""Create a search object for records and returns the record ids using a scan() query.""" | ||
search = records_service.create_search( | ||
identity, | ||
records_service.record_cls, | ||
records_service.config.search, | ||
permission_action="read", | ||
extra_filter=records_q, | ||
) | ||
|
||
yield from map(lambda x: x.id, search.scan()) | ||
|
||
|
||
def transfer_communities( | ||
identity, communities, new_parent, records_q=None, set_default=False | ||
): | ||
"""Transfer communities and records to new parent. | ||
Usage 1 - transfer all the records: | ||
.. code-block:: python | ||
identity = ... | ||
communities = ["a_small_eu_project", "test_eu_project"] | ||
new_parent = "the_eu_community" | ||
transfer_communities(identity, communities, new_parent) | ||
Usage 2 - transfer only the records that match a specific query and set the new parent as default: | ||
.. code-block:: python | ||
identity = ... | ||
communities = ["a_small_eu_project", "test_eu_project"] | ||
new_parent = "the_eu_community" | ||
records_q = dsl.query.Bool( | ||
"must", | ||
must=[ | ||
dsl.Q("terms", **{"parent.communities.ids": community_ids}), | ||
dsa.Q("term", **{"metadata.publication_date": ""}) | ||
], | ||
) | ||
transfer_communities(identity, communities, new_parent, records_q, set_default=True) | ||
:param identity: The identity of the user performing the action. | ||
:param communities: The list of communities to transfer. | ||
:param new_parent: The new parent community to transfer the communities to. | ||
:param records_q: The query to filter the records to transfer. If not provided, all the records will be transferred. | ||
:param set_default: Whether to set the new parent as the default community of the records. Default is False. | ||
""" | ||
if not records_q: | ||
records_q = _all_records_q(communities) | ||
|
||
with UnitOfWork() as uow: | ||
# Step 1 - move communities to new target using communities service | ||
community_service.bulk_add_to_parent(identity, communities, new_parent, uow=uow) | ||
|
||
# Step 2 - move records to new parent using community records service | ||
record_ids = _search_records(identity, records_q) | ||
records_communities_service.bulk_add( | ||
identity, new_parent, record_ids, set_default=set_default, uow=uow | ||
) | ||
uow.commit() | ||
|
||
|
||
def transfer_records(identity, records, new_parent, set_default=False): | ||
"""Transfer records to new parent. | ||
Usage: | ||
.. code-block:: python | ||
identity = ... | ||
records = ["1234561", "1234321"] | ||
new_parent = "the_eu_community" | ||
transfer_records(identity, records, new_parent) | ||
:param identity: The identity of the user performing the action. | ||
:param records: The list of records to transfer. | ||
:param new_parent: The new parent community to transfer the records to. | ||
:param set_default: Whether to set the new parent as the default community of the records. Default is False. | ||
""" | ||
with UnitOfWork() as uow: | ||
records_communities_service.bulk_add( | ||
identity, new_parent, records, set_default=set_default, uow=uow | ||
) | ||
uow.commit() | ||
|
||
|
||
from invenio_access.permissions import system_identity | ||
|
||
ids = ["214"] # from the_best_eu_project | ||
target_comm = "test" | ||
# transfer_records(system_identity, ids, target_comm) | ||
transfer_communities(system_identity, ["a_new_one"], target_comm) |