DataManager Reference Guide

This guide is for versions Beta 47+


Source code

Background Information: A Technology Stack on Top of a (Neo4j) Graph Database

Class DataManager

    For general, high-level database-interaction operations.
    Used by the UI for Page Generation,
    as well as by the web API to produce data for the endpoints.

    This library is primarily a common entry point for data requests:
    many specific operations get delegated to other, more specialized, libraries.

    Static class that does NOT get instantiated;
    however, it must be initialized with a call to set_database()

    
nameargumentsreturns
set_databasedb :NeoAccessNone
        IMPORTANT: this method MUST be called before using this class!

        :param db:  Database-interface object, created with the NeoAccess library
        :return:    None
        
nameargumentsreturns
get_node_labels [str]
        Look up and return a list of all the node labels in the database.
        EXAMPLE: ["my_label_1", "my_label_2"]

        :return:    A list of strings
        
nameargumentsreturns
add_new_labellabel: strint
        Create a new blank node with the specified label.
        Mostly used for testing.

        :return:    The internal database ID of the new node
        

UTILITIES

nameargumentsreturns
to_int_if_possibles: str
        Convert the argument to an integer, if at all possible; otherwise, leave it as a string
        (or leave it as None, if applicable)

        :param s:   Value to convert to integer, if possible
        :return:    Either an int version of the passed value, or that same value
        
nameargumentsreturns
str_to_ints: strint
        Helper function to give more friendly error messages in case non-integers are passed
        in situations where integers are expected.
        Without this function, the user would see cryptic messages such as
        "invalid literal for int() with base 10: 'q123'"

        EXAMPLE of usage:
            try:
                i = cls.str_to_int(i_str)
            except Exception as ex:
                # Do something

        :param s:   A string that should represent an integer
        :return:    The integer represented in the passed string, if applicable;
                        if not, an Exception is raised
        

SCHEMA RELATED

nameargumentsreturns
all_schema_classes [str]
        Return a list of all the existing Schema classes
        :return:
        
nameargumentsreturns
get_schema_visualization_data 
        Create and return an object with all the info
        to visualise a graph with the database Schema info

        :return:    An object of class PyGraphScape
        
nameargumentsreturns
new_schema_classclass_specs: dictNone
        Create a new Schema Class, possibly linked to another existing class,
        and also - typically but optionally - with the special "INSTANCE_OF" link
        to an existing class (often, "Records")
        In case of error, an Exception is raised.

        :param class_specs: A dictionary with the following
                DICTIONARY KEYS:
                new_class_name      The name of the new Class (tolerant of leading/trailing blanks)
                properties_list     The name of all desired Properties, in order
                                    (all comma-separated).  Tolerant of leading/trailing blanks, and of missing property names
                instance_of         Typically, "Records"

                [ALL THE REMAINING KEYS ARE OPTIONAL]
                linked_to           The name of an existing Class node, to link to
                rel_name            The name to give to the above relationship
                rel_dir             The relationship direction, from the point of view of the newly-added node

        :return:            None
        
nameargumentsreturns
add_schema_relationship_handlerclass_specs: dictNone

        In case of error, an Exception is raised.

        :param class_specs: A dictionary with the following
                DICTIONARY KEYS:
                    from_class_name
                    to_class_name
                    rel_name

        :return: None
        
nameargumentsreturns
schema_add_property_to_class_handlerspecs_dict: dictNone
        Add a new Property to an existing Classes

        In case of error, an Exception is raised.

        :param specs_dict: A dictionary with the following
                DICTIONARY KEYS:
                    prop_name       (any leading/trailing blanks are ignored)
                    class_name      (any leading/trailing blanks are ignored)

        :return: None
        
nameargumentsreturns
delete_schema_relationship_handlerclass_specs: dictNone
        Delete the relationship(s) with the specified name
        between the 2 existing Class nodes (identified by their respective names),
        going in the from -> to direction direction.

        In case of error, an Exception is raised.

        :param class_specs: A dictionary with the following
                DICTIONARY KEYS:
                    from_class_name
                    to_class_name
                    rel_name

        :return: None
        

CONTENT RELATED

nameargumentsreturns
add_data_relationship_handlerdata_dict: dictNone
        Add the specified relationship (edge) between data nodes.
        In case of error, an Exception is raised.

        :param data_dict: A dictionary with the following
                from                    The uri of the node from which the relationship originates
                to                      The uri of the node into which the relationship takes
                rel_name                The name of the relationship to add
                schema_code (optional)  If passed, the appropriate plugin gets invoked

        :return: None
        
nameargumentsreturns
remove_data_relationship_handlerdata_dict: dictNone
        Remove the specified relationship (edge) between data nodes.
        In case of error, an Exception is raised.

        :param data_dict: A dictionary with the following
                DICTIONARY KEYS:
                    from                    The uri of the node from which the relationship originates
                    to                      The uri of the node into which the relationship takes
                    rel_name                The name of the relationship to remove
                    schema_code (optional)  If passed, the appropriate plugin gets invoked

        :return: None
        
nameargumentsreturns
get_leaf_records [str]
        Get all Classes that are, directly or indirectly, INSTANCE_OF the Class "Records",
        as long as they are leaf nodes (with no other Class that is an INSTANCE_OF them.)

        EXAMPLE: if the "Foreign Vocabulary" Class is an INSTANCE_OF the Class "Records",
                 and if "French Vocabulary" and "German Vocabulary" are instances of "Foreign Vocabulary",
                 then "French Vocabulary" and "German Vocabulary" (but NOT "Foreign Vocabulary")
                 would be returned

        :return: A list of strings with the Class names
                 EXAMPLE:
                    ["Cuisine Type","Entrees","French Vocabulary","German Vocabulary","Restaurants","Site Link"]
        
nameargumentsreturns
get_text_media_contenturi :str, public_required = Falsestr
        Fetch and return the contents of a media item stored on a local file,
        optionally requiring it to be marked as "public".

        :param uri:             A string identifying the desired Content Item, which ought to be text media
        :param public_required: If True, the Content Item is returned
                                    only if its database node has an the attribute "public: true"

        :return:                A string with the HTML text of the requested note;
                                    or an Exception in case of failure
                                    (e.g., if public_required is True and the item isn't public)
        
nameargumentsreturns
get_records_by_classclass_name :str, field_name :str, order_by :str[]
        Return a list of values of a particular field, of all the records of the given Class,
        optionally sorted by the given field

        :param class_name:
        :param field_name:
        :param order_by:
        :return:            A list of values
        
nameargumentsreturns
get_records_by_linkrequest_data: dict[dict]
        Locate and return the data of the nodes linked to the one specified by uri,
        by the relationship named by rel_name, in the direction specified by dir

        :param request_data: A dictionary with 3 keys, "uri", "rel_name", "dir"
        :return:             A list of dictionaries with all the properties of the neighbor nodes
        
nameargumentsreturns
get_link_summaryuri :str, omit_names = Nonedict
        Return a dictionary structure identifying the names and counts of all
        inbound and outbound links to/from the given data node.

        :param uri:         String with the URI of a data node
        :param omit_names:  Optional list of relationship names to disregard
        :return:            A dictionary with the names and counts of inbound and outbound links.
                            Each inner list is a pair [name, count]
                            EXAMPLE:
                                {
                                    "in": [
                                        ["BA_served_at", 1]
                                    ],
                                    "out": [
                                        ["BA_located_in", 1],
                                        ["BA_cuisine_type", 2]
                                    ]
                                }
        
nameargumentsreturns
update_content_itemuri :str, class_name :str, update_data: dictNone
        Update an existing Content Item.
        No harm if new values are identical to the earlier old values.
        Note: class_name is redundant

        Notes:
            - if a field is blank, it gets completely dropped from the node
            - leading/trailing blanks in the field values are stripped away

        :param uri:         String with a unique identifier for the Content Item to update
        :param class_name:  Name of the Schema Class of the Content Item
        :param update_data: A dict of data field names and their desired new values
        :return:            None
        
nameargumentsreturns
delete_content_itemuri: str, class_name: strNone
        Delete the specified individual Content Item.
        Note:  class_name is redundant; used as a safety mechanism
               against incorrect values of their uri

        :param uri:         String version of the unique ID
        :param class_name:  Name of the Schema Class of the Content Item
        :return:            None
        
nameargumentsreturns
create_data_nodeclass_name :str, item_data: dictdict
        Create a new Data Node.

        RESTRICTION: currently, not to be used for any Content Item that
                     requires plugin-specific actions

        :param class_name:
        :param item_data:

        :return:            A dict with the internal database ID and uri
                                assigned to the newly-created node
                                EXAMPLE: {"internal_id": 123, "uri": "rs-8"}
        
nameargumentsreturns
add_new_content_item_to_categorycategory_uri :str, class_name :str, insert_after :str, item_data: dictstr
        Create a new Content Item attached to a particular Category,
        at a specified position on the Category page

        NOTE: this is a newer version of new_content_item_in_category()

        :param category_uri:    String to identify the Category that we're linking to
        :param class_name:      Name of the Class of the new Content Item
        :param insert_after:    Either the URI of an existing Content Item attached to this Category,
                                    or one of the special values "TOP" or "BOTTOM"
        :param item_data:       Dict with all applicable plugin-specific fields (all the key/values for the new Content Item)

        :return:    The URI of the newly-created Data Node
        
nameargumentsreturns
new_content_item_in_categorypost_data: dictstr
        NOTE: this method will be phased out in favor of add_new_content_item_to_category()
        Create a new Content Item attached to a particular Category,
        at a specified position on the Category page

        :param post_data:   A dict containing the following keys
            - "category_id"  (for the linking to a Category)
            - Schema-related keys:
                    * schema_uri (Optional)
                    * class_name (Required only for Class Items of type "record")

            - insert_after        Either the URI of an existing Content Item attached to this Category,
                                  or one of the special values "TOP" or "BOTTOM"
            - *PLUS* all applicable plugin-specific fields (all the key/values for the new Content Item)

        :return:    The URI of the newly-created Data Node.
                    In case of error, an Exception is raised
        
nameargumentsreturns
new_content_item_in_category_final_stepinsert_after :str, category_id :str, new_uri, class_name, post_data, original_post_data


CATEGORY RELATED

nameargumentsreturns
switch_categorydata_dictNone
        Switch one or more Content Items from being attached to a given Category,
        to another one

        :param data_dict:   Dict with 3 keys:
                                items   list of string URI's of Content Items
                                        to relocate across Categories
                                from    URI of the old Category
                                to      URI of the new Category
        :return:            None
        

SEARCH

nameargumentsreturns
search_for_termswords :str, search_category=""([dict], str)
        Carry out a full-text search for a word, or set of words - possibly restricted to some Categories

        :param words:       String containing one or more words to search for
        :param search_category: (OPTIONAL) URI of Category.  If supplied, all searching will
                                    be limited to Content Items in this Category
                                    or in any of its sub-categories
        :return:            A pair consisting of:
                                1) list of dictionaries, each with the record data of a search result
                                2) a string with a caption to describe these search results
        
nameargumentsreturns
search_for_wordword :str, search_category=""[dict]
        Look up any stored words that contains the requested string
        (ignoring case and leading/trailing blanks.)

        Then locate the Content nodes that are indexed by any of those words.
        Return a (possibly empty) list of the data of all the found nodes.

        :param word:    A string, typically containing a word or word fragment;
                            case and leading/trailing blanks are ignored
        :param search_category: (OPTIONAL) URI of Category.  If supplied, all searching will
                                    be limited to Content Items in this Category
                                    or in any of its sub-categories
        :return:        A list of dictionaries, each with the record data of a search result
        
nameargumentsreturns
search_for_all_wordsword_list :[str], search_category=""[dict]
        Look up any stored words that contains the requested string
        (ignoring case and leading/trailing blanks.)

        Then locate the Content nodes that are indexed by any of those words.
        Return a (possibly empty) list of the data of all the found nodes.

        :param word_list:   A list of strings, each typically containing a word or word fragment;
                                case and leading/trailing blanks are ignored
        :param search_category: (OPTIONAL) URI of Category.  If supplied, all searching will
                                    be limited to Content Items in this Category
                                    or in any of its sub-categories
        :return:            A list of dictionaries, each with the record data of a search result
        
nameargumentsreturns
extract_website_titleurl :strstr
        Retrieve the Title of a remote webpage, given its URL

        :param url: URL of the website whose title we want to fetch.
                        EXAMPLE:  "https://brainannex.org"
        :return:    The "Title" of the website.
                        In case unable to locate the web page, or unable to extract its Title,
                        raise an Exception
        

FILTERS

nameargumentsreturns
get_nodes_by_filterfilter_dict :dict[dict]
        Return the list of the database nodes that match all the requirements spelled out in the given filter

        :param filter_dict: A dictionary, with keys:
                                "label"         The name of a node label
                                "class_name"    NOT CURRENTLY IMPLEMENTED
                                "key_name"      A string with the name of a node attribute;
                                                    if provided, key_value must be passed, too
                                "key_value"     The required value for the above key; if provided, key_name must be passed, too.
                                                    Note: no requirement for the key to be primary
                                "clause"        NOT CURRENTLY IMPLEMENTED
                                                    MUST use "n" as dummy name.
                                                    EXAMPLE: "n.name CONTAINS 'art'"
                                "order_by"      Field name, or comma-separated list;
                                                    each name may optionally be followed by "DESC"
                                                    NOTE: if ordering by a non-existing field, "skip" may not work as expected;
                                                          this seems to be a Cypher/Neo4j bug
                                "skip"          The number of initial entries (in the context of specified order) to skip
                                "limit"         The max number of entries to return
                            EXAMPLES:
                                {"label": "BA", "key_name": "uri", "key_value": "sl-123"}
                                {"label": "doctor", "limit": 25, "skip": 50}
                                {'label': 'YouTube Channel', 'clause': "n.name CONTAINS 'sc'", 'order_by': 'name'}
                                {'label': 'Quote', 'clause': "n.quote CONTAINS 'kiss'", 'order_by': 'attribution,quote'}

        :return:            A (possibly-empty) list of dictionaries; each dict contains the data for a node
        

IMPORT EXPORT

nameargumentsreturns
export_full_dbase dict
        Export the entire Neo4j database as a JSON string.

        IMPORTANT: APOC must be activated in the database, to use this function.
                   Otherwise it'll raise an Exception

        EXAMPLE:
        { 'nodes': 2,
          'relationships': 1,
          'properties': 6,
          'data': '[{"type":"node","id":"3","labels":["User"],"properties":{"name":"Adam","age":32,"male":true}},\n
                    {"type":"node","id":"4","labels":["User"],"properties":{"name":"Eve","age":18}},\n
                    {"id":"1","type":"relationship","label":"KNOWS","properties":{"since":2003},"start":{"id":"3","labels":["User"]},"end":{"id":"4","labels":["User"]}}\n
                   ]'
        }

        :return:    A dictionary specifying the number of nodes exported ("nodes"),
                    the number of relationships ("relationships"),
                    and the number of properties ("properties"),
                    as well as a "data" field with the actual export as a JSON string
        
nameargumentsreturns
upload_import_jsonfiles, upload_dir :str, return_url=None, verbose=Falsestr
        Modify the database, based on the contents of the uploaded file (expected to contain the JSON format
        of a Neo4j export)

        :param files:       An ImmutableMultiDict object.
                                EXAMPLE: ImmutableMultiDict([('imported_datafile', )])
                                    where 'imported_datafile' originates from 
                                    and the name after FileStorage is the name of the file being uploaded
        :param upload_dir:  Name of a temporary folder for file uploads.  EXAMPLE: "D:/tmp/"
        :param return_url:
        :param verbose:
        :return:            Status string (error or success message)
        
nameargumentsreturns
upload_import_json_filefiles, upload_dir :str, post_pars, verbose=Falsestr
        Manage the upload and import into the database of a data file in JSON format.

        :param files:       An ImmutableMultiDict object.
                                EXAMPLE: ImmutableMultiDict([('imported_datafile', )])
                                    where 'imported_datafile' originates from 
                                    and the name after FileStorage is the name of the file being uploaded
        :param upload_dir:  Name of a temporary folder for file uploads.  EXAMPLE: "D:/tmp/"
        :param post_pars:
        :param verbose:
        :return:            Status string, if successful.  In case of error, an Exception is raised
        
nameargumentsreturns
data_intake_status 

nameargumentsreturns
do_stop_data_intake None
        Request that the continuous data import cease upon the completion of the current import

        :return:    None
        
nameargumentsreturns
do_bulk_importintake_folder: str, outtake_folder: str, schema_class: strstr
        Bulk-import all the JSON files in the intake_folder directory.
        The import will continue until the folder is empty,
        or until the cls.ongoing_data_intake property is set to False

        Failure of individual imports is logged, but does not terminate the operation.
        An Exception is raised if any of the following happens:
            * The log file cannot be accessed/created
            * Any of the data files cannot be moved to their final destination

        :param intake_folder:   Name of folder (ending with "/") where the files to import are located
        :param outtake_folder:
        :param schema_class:
        :return: 
        
nameargumentsreturns
process_file_to_importf: str, intake_folder: str, outtake_folder: str, schema_class: strNone
        Import a JSON file, located in a particular folder, and then move it to a designated folder.
        Keep a log of the operations.
        Exceptions are caught and logged; if the Exceptions involves moving the process file, a new one is raised

        :param f:               Name of file to import
        :param intake_folder:   Name of folder (ending with "/") where the files to import are located
        :param outtake_folder:
        :param schema_class:
        :return:                None
        
nameargumentsreturns
archive_data_filesrc_fullname, dest_fullname, outtake_folderNone
        Move the processed file to its final location.
        In case of error, the Exception is caught, logged and re-raised

        :param src_fullname:
        :param dest_fullname:
        :param outtake_folder:
        :return:                None
        
nameargumentsreturns
define_pattern str
        Define a REGEX pattern for parsing of data files, for use in import_datafile()

        The pattern is expected to be used in a re.findall() that uses re.DOTALL as the last argument

        :return:    A string with a REGEX pattern
        

LOGGING

nameargumentsreturns
init_logfile None
        Prepare a handle for the log file

        :return:
        
nameargumentsreturns
append_to_logmsgNone

        :param msg:
        :return: