class_docstr: This entity may change or be removed in a future release without warning.
  SQLAlchemy compliant backend store for tracking meta data for MLflow entities. MLflow
  supports the database dialects ``mysql``, ``mssql``, ``sqlite``, and ``postgresql``.
  As specified in the
  `SQLAlchemy docs <https://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls>`_ ,
  the database URI is expected in the format
  ``<dialect>+<driver>://<username>:<password>@<host>:<port>/<database>``. If you do not
  specify a driver, SQLAlchemy uses a dialect's default driver.
  
  This store interacts with SQL store using SQLAlchemy abstractions defined for MLflow entities.
  :py:class:`mlflow.store.model_registry.models.RegisteredModel` and
  :py:class:`mlflow.store.model_registry.models.ModelVersion`
docstr: Search for model versions in backend that satisfy the filter criteria.
  
  :param filter_string: A filter string expression. Currently supports a single filter
                        condition either name of model like ``name = 'model_name'`` or
                        ``run_id = '...'``.
  :param max_results: Maximum number of model versions desired.
  :param order_by: List of column names with ASC|DESC annotation, to be used for ordering
                   matching search results.
  :param page_token: Token specifying the next page of results. It should be obtained from
                      a ``search_model_versions`` call.
  :return: A PagedList of :py:class:`mlflow.entities.model_registry.ModelVersion`
           objects that satisfy the search expressions. The pagination token for the next
           page can be obtained via the ``token`` attribute of the object.
docstr_tok: ["Search","for","model","versions","in","backend","that","satisfy","the","filter","criteria",".",":","param","filter_string",":","A","filter","string","expression",".","Currently","supports","a","single","filter","condition","either","name","of","model","like","``","name","=","'model_name","'","``","or","``","run_id","=","'","...","'","``",".",":","param","max_results",":","Maximum","number","of","model","versions","desired",".",":","param","order_by",":","List","of","column","names","with","ASC|DESC","annotation",",","to","be","used","for","ordering","matching","search","results",".",":","param","page_token",":","Token","specifying","the","next","page","of","results",".","It","should","be","obtained","from","a","``","search_model_versions","``","call",".",":","return",":","A","PagedList","of",":","py",":","class",":","`","mlflow.entities.model_registry.ModelVersion","`","objects","that","satisfy","the","search","expressions",".","The","pagination","token","for","the","next","page","can","be","obtained","via","the","``","token","``","attribute","of","the","object","."]
code: def search_model_versions(
      self,
      filter_string=None,
      max_results=SEARCH_MODEL_VERSION_MAX_RESULTS_DEFAULT,
      order_by=None,
      page_token=None,
  ):
      """
      Search for model versions in backend that satisfy the filter criteria.
  
      :param filter_string: A filter string expression. Currently supports a single filter
                            condition either name of model like ``name = 'model_name'`` or
                            ``run_id = '...'``.
      :param max_results: Maximum number of model versions desired.
      :param order_by: List of column names with ASC|DESC annotation, to be used for ordering
                       matching search results.
      :param page_token: Token specifying the next page of results. It should be obtained from
                          a ``search_model_versions`` call.
      :return: A PagedList of :py:class:`mlflow.entities.model_registry.ModelVersion`
               objects that satisfy the search expressions. The pagination token for the next
               page can be obtained via the ``token`` attribute of the object.
      """
      if not isinstance(max_results, int) or max_results < 1:
          raise MlflowException(
              "Invalid value for max_results. It must be a positive integer,"
              f" but got {max_results}",
              INVALID_PARAMETER_VALUE,
          )
  
      if max_results > SEARCH_MODEL_VERSION_MAX_RESULTS_THRESHOLD:
          raise MlflowException(
              "Invalid value for request parameter max_results. It must be at most "
              f"{SEARCH_MODEL_VERSION_MAX_RESULTS_THRESHOLD}, but got value {max_results}",
              INVALID_PARAMETER_VALUE,
          )
  
      parsed_filters = SearchModelVersionUtils.parse_search_filter(
          filter_string
      )
  
      filter_query = self._get_search_model_versions_filter_clauses(
          parsed_filters, self.engine.dialect.name
      )
  
      parsed_orderby = self._parse_search_model_versions_order_by(
          order_by
          or [
              "last_updated_timestamp DESC",
              "name ASC",
              "version_number DESC",
          ]
      )
      offset = SearchUtils.parse_start_offset_from_page_token(
          page_token
      )
      # we query for max_results + 1 items to check whether there is another page to return.
      # this remediates having to make another query which returns no items.
      max_results_for_query = max_results + 1
  
      with self.ManagedSessionMaker() as session:
          query = (
              filter_query.options(
                  *self._get_eager_model_version_query_options()
              )
              .filter(
                  SqlModelVersion.current_stage
                  != STAGE_DELETED_INTERNAL
              )
              .order_by(*parsed_orderby)
              .limit(max_results_for_query)
          )
          if page_token:
              query = query.offset(offset)
          sql_model_versions = (
              session.execute(query).scalars(SqlModelVersion).all()
          )
          next_page_token = self._compute_next_token(
              max_results_for_query,
              len(sql_model_versions),
              offset,
              max_results,
          )
          model_versions = [
              mv.to_mlflow_entity() for mv in sql_model_versions
          ][:max_results]
          return PagedList(model_versions, next_page_token)
  
imports: import logging
  import urllib
  import sqlalchemy
  from sqlalchemy.future import select
  import mlflow.store.db.utils
  from mlflow.entities.model_registry.model_version_stages import ALL_STAGES, DEFAULT_STAGES_FOR_GET_LATEST_VERSIONS, STAGE_ARCHIVED, STAGE_DELETED_INTERNAL, get_canonical_stage
  from mlflow.exceptions import MlflowException
  from mlflow.protos.databricks_pb2 import INVALID_PARAMETER_VALUE, INVALID_STATE, RESOURCE_ALREADY_EXISTS, RESOURCE_DOES_NOT_EXIST
  from mlflow.store.artifact.utils.models import _parse_model_uri
  from mlflow.store.entities.paged_list import PagedList
  from mlflow.store.model_registry import SEARCH_MODEL_VERSION_MAX_RESULTS_DEFAULT, SEARCH_MODEL_VERSION_MAX_RESULTS_THRESHOLD, SEARCH_REGISTERED_MODEL_MAX_RESULTS_DEFAULT, SEARCH_REGISTERED_MODEL_MAX_RESULTS_THRESHOLD
  from mlflow.store.model_registry.abstract_store import AbstractStore
  from mlflow.store.model_registry.dbmodels.models import SqlModelVersion, SqlModelVersionTag, SqlRegisteredModel, SqlRegisteredModelAlias, SqlRegisteredModelTag
  from mlflow.utils.search_utils import SearchModelUtils, SearchModelVersionUtils, SearchUtils
  from mlflow.utils.time import get_current_time_millis
  from mlflow.utils.uri import extract_db_type_from_uri
  from mlflow.utils.validation import _validate_model_alias_name, _validate_model_name, _validate_model_version, _validate_model_version_tag, _validate_registered_model_tag, _validate_tag_name
label_desc: Use image node_id 32 for calling the SqlAlchemyStore obj's underlying member method code with example usage: obj.search_model_versions(filter_string, max_results, order_by, page_token) and returns: PagedList