honmaple / flask-msearch

Full text search for flask.
BSD 3-Clause "New" or "Revised" License
214 stars 30 forks source link

XXX.query.msearch() search nothing #63

Open Hardman233 opened 2 weeks ago

Hardman233 commented 2 weeks ago

Hello,After using flask sqlalchemy, the search does not yield any data. The code is as follows: search_config:

from flask_msearch import Search
from jieba.analyse import ChineseAnalyzer
from utils.read_yaml import YAML

class SearchConfig:
    _instance = None 

    def __new__(cls, db=None, app=None):
        if cls._instance is None:
            cls._instance = super(SearchConfig, cls).__new__(cls)
            cls._instance.search = Search(db=db, analyzer=ChineseAnalyzer())  
            if app is not None:
                cls._instance.init_app(app)
        return cls._instance

    def init_app(self, app):
        search_config = YAML.ReadRoot("search")

        if not search_config:
            raise ValueError("Search config is missing in YAML.")

        app.config['MSEARCH_INDEX_NAME'] = search_config['MSEARCH_INDEX_NAME']
        app.config['MSEARCH_BACKEND'] = search_config['MSEARCH_BACKEND']
        app.config['MSEARCH_PRIMARY_KEY'] = search_config['MSEARCH_PRIMARY_KEY']
        app.config['MSEARCH_ENABLE'] = search_config['MSEARCH_ENABLE']
        app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = search_config['SQLALCHEMY_TRACK_MODIFICATIONS']

        self.search.init_app(app)

    def get_search_instance(self):
        return self.search

app_config.py:

from flask import Flask
from utils.enums import FilePath
from flask_cors import CORS
from utils.read_yaml import YAML
from datetime import timedelta
from configs.db_config import MySQLPools
from configs.blueprints_config import RegisterBlueprints
from configs.middleware_config import Middleware
from configs.nosql_config import RedisClient, RedisCacheConfig
from configs.jwt_config import JWTConfig
from configs.search_config import SearchConfig
from configs.websocket_config import create_server
from configs.mail_config import mail_config
from configs.db_config import SQLAlchemyConfig
from configs.exception_config import register_error_handlers
from configs.url_config import build_route_config

redis_config = RedisCacheConfig()
security = YAML.ReadRoot('security')

def create_app():
    """工厂函数,用于将所有组件全局注册"""
    app = Flask(__name__, template_folder=FilePath.TEMPLATES_PATH.value)
    """解决数据编码问题"""
    app.json.ensure_ascii = False
    CORS(app, resources=r'/*')
    app.secret_key = security['SECRET_KEY']
    app.config['JWT_SECRET_KEY'] = security['JWT_SECRET_KEY']
    app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(seconds=security['PERMANENT_SESSION_LIFETIME'])
    register_error_handlers(app)  # 注册异常
    mysql_pool = MySQLPools()  # 初始化 MySQL 连接池
    pool_store = mysql_pool.DynamicCreateConnectionPools()  # 动态创建连接池
    if pool_store: app.config['POOL_STORE'] = pool_store  # 全局注册连接池
    # 为redis库中
    # redis_client = RedisClient().redis_client
    # app.config['REDIS_CLIENT'] = redis_client
    # 为flask-cache中的redis缓存
    RegisterBlueprints(app)  # 注册蓝图, 要放在ROUTE_CONFIG前面要不然读不到蓝图的rule
    redis_config.init_app(app=app)
    JWTConfig(app).init_app(app)
    db = SQLAlchemyConfig(app).init_app(app)  # 初始化 SQLAlchemyConfig
    # print(app.extensions['sqlalchemy'].__dict__)
    SearchConfig(app=app, db=db).init_app(app)  # 初始化全文搜索
    ROUTE_CONFIG = build_route_config(app)  # 注册验证路由
    Middleware(app, ROUTE_CONFIG)  # 注册钩子函数
    mail_config.init_app(app)  # 注册邮箱插件
    # app, socketio = create_server(app)  # 心跳检测
    return app

models.py , service.py and views.py:

# coding: utf-8
from modules.collection import db
from modules.base.base_model import BaseModel

class User(BaseModel):
    __tablename__ = 'users'
    __searchable__ = ['name', 'email']

    id = db.Column(db.Integer, primary_key=True, autoincrement=True, unique=True)
    email = db.Column(db.String(255), nullable=False, unique=True, comment='注册邮箱')
    password = db.Column(db.String(255), nullable=False)
    name = db.Column(db.String(255), comment="用户真实姓名")
    instrument_level = db.Column(db.Integer, comment="乐器水平,1-10")
    telephone = db.Column(db.String(255))
    is_activate = db.Column(db.Boolean, default=False, comment="用户是否激活")
    age = db.Column(db.Integer)
    sex = db.Column(db.Integer, default=-1)
    desc = db.Column(db.Text)

class UserService:
  @staticmethod
    def test_search(keyword):
        return User.query.msearch(keyword, fields=['name', 'email'], limit=20, or_=True, rank_order=True).all()

@users.route('/search', methods=['GET'])
def search():
    keyword = request.args.get('keyword')
    users = UserService.test_search(keyword)

    return Response(data=[user.to_dict() for user in users])
honmaple commented 2 weeks ago

What is search_config? If the database is old data, please use search.create_index() to create index manually.