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 }}
感谢您的帮助。
我相信原因是你到第 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 认为它在执行新查询时不是吗?