Flask-paginate + MongoDB 全文搜索错误 $search 在点击第 2 页时类型错误

问题描述 投票:0回答:1

flask-paginate 和 pyMongo/MongoDB 全文搜索有问题。分页对我来说效果很好,直到用户尝试在数据库中搜索“帖子”。它将显示前 6 个结果(正如我在本例中设置的那样),但是一旦您想要导航到第 2 页,它就会抛出错误:

pymongo.errors.OperationFailure: "$search" had the wrong type. Expected string, found null, full error: {'operationTime': Timestamp(1600978481, 2), 'ok': 0.0, 'errmsg': '"$search" had the wrong type. Expected string, found null', 'code': 14, 'codeName': 'TypeMismatch', '$clusterTime': {'clusterTime': Timestamp(1600978481, 2), 'signature': {'hash': b'\xd6b\xe7\x8eI\xa5\xea[\xb2\x0e5Y\xa2\xf3\x93R\xc6\xc1\xc4\x06', 'keyId': 6862628668309504003}}}

如果我尝试使用

.sort("param", 1)
过滤搜索结果,则会出现同样的问题 - 我已经删除了此“功能”,但这与我遇到的错误相同。

Werkzeug 指出问题出现在我的 search() 路线的第 63 行,即。

pagination = Pagination(...)

我的路线.py:

@app.route('/search', methods=("GET", "POST"))
def search():
    page = request.args.get(get_page_parameter(), type=int, default=1)
    per_page = 6
    search_request = request.form.get("search")
    all_posts = mongo.db.posts.find({"$text": {"$search": search_request}}).skip((page-1) * per_page).limit(per_page)
    pagination = Pagination(
        page=page, per_page=per_page,
        total=all_posts.count(), record_name='all_posts')
    return render_template('search.html', all_posts=all_posts, pagination=pagination, search_request=search_request)

我的search.html模板:

<div class="row">
        {% for post in all_posts %}
        <div class="col s12 l4">
            <div class="card card-panel hoverable">
                <div class="card-image center-align">
                    <img src="{{post.image_url}}" class="card-img">
                </div>
                <div class="card-content">
                    <h4 class="card-title">{{post.title}}</h4>
                    <p>{{post.description}}</p>
                    <p class="read-time">{{post.read_time}} minute(s), {{post.views}} views</p>
                </div>
                <div class="card-action">
                    <a href="{{url_for('post_page', post_id=post._id)}}" class="card-link">Read</a>
                </div>
            </div>
        </div>
        {% endfor %}
        {% if all_posts.count() == 0 %}
        <div class="center-align">
            <h3>No posts found</h3>
        </div>
        {% endif %}
    </div>
    <!-- Pagination -->
    <div class="row center-align">
        {% if all_posts.count() > 1 %}
        {{ pagination.info }}
        {% endif %}
        {{ pagination.links }}

感谢您的帮助。

mongodb flask pymongo
1个回答
0
投票

我相信原因是你到第 2 页的链接将再次调用 search() 路由函数(page=2),但它不会具有原始形式的搜索参数。

您可以使用flask.session来保留您的搜索词,如下所示:

def imageSearchResults(page=1):
    if request.args.get('search'):
        print("Resetting Search Term")
        searchTerm = request.args.get('search')
        session['currentSearchTerm'] = searchTerm
    else:
        searchTerm = session['currentSearchTerm']
        print("Still working with", searchTerm)

    theseImgs = Mongo_Imgs.objects.search_text(searchTerm).order_by("$text_score").paginate(page, current_app.config['NOTES_PER_PAGE'])
    return render_template('searchimages.html',
                            records=theseImgs,
                            search=searchTerm)

现在,您可能会认为分页的全部目的是避免每个页面都访问数据库,那么为什么我们需要保留搜索词呢? 至少我认为 - 并阅读 mongoengine 文档,它说:

从 MongoEngine 0.8 开始,查询集使用本地缓存。所以 多次迭代只会导致一次查询。如果这是 这不是您想要的行为,您可以调用 no_cache (版本 0.8.3+)来 返回一个非缓存查询集

我还没有找到关于这个问题的明确答案,但我认为查询可能在缓存中用哈希或其他东西来标识,并且这有点欺骗 Flask 认为它在执行新查询时不是吗?

© www.soinside.com 2019 - 2024. All rights reserved.