如何在gae中使用游标进行搜索?

时间:2013-05-21 06:01:34

标签: google-app-engine python-2.7 cursor

当我使用RTFM时,我无法理解如何使用manual中描述的技术指定分页搜索。这是我的代码:

def find_documents(query_string, limit, cursor):
    try:
        subject_desc = search.SortExpression(
            expression='date',
            direction=search.SortExpression.DESCENDING,
            default_value=datetime.now().date())

        # Sort up to 1000 matching results by subject in descending order
        sort = search.SortOptions(expressions=[subject_desc], limit=1000)

        # Set query options
        options = search.QueryOptions(
            limit=limit,  # the number of results to return
            cursor=cursor,
            sort_options=sort,
            #returned_fields=['author', 'subject', 'summary'],
            #snippeted_fields=['content']
         )
        query = search.Query(query_string=query_string, options=options)
        index = search.Index(name=_INDEX_NAME)
        # Execute the query
        return index.search(query)
    except search.Error:
        logging.exception('Search failed')
    return None


class MainAdvIndexedPage(SearchBaseHandler):
    """Handles search requests for comments."""

    def get(self):
        """Handles a get request with a query."""
        regionname = 'Delhi'
        region = Region.all().filter('name = ', regionname).get()
        uri = urlparse(self.request.uri)
        query = ''
        if uri.query:
            query = parse_qs(uri.query)
            query = query['query'][0]

        results = find_documents(query, 50, search.Cursor())
        next_cursor = results.cursor
        template_values = {
            'results': results,'next_cursor':next_cursor,
            'number_returned': len(results.results),
            'url': url, 'user' : users.get_current_user(), 
            'url_linktext': url_linktext, 'region' : region, 'city' : '', 'request' : self.request, 'form' : SearchForm(), 'query' : query
        }
        self.render_template('indexed.html', template_values)

上面的代码可以工作并进行搜索,但不会对结果进行分页。我想知道手册中的以下代码:

next_cursor = results.cursor

next_cursor_urlsafe = next_cursor.web_safe_string
# save next_cursor_urlsafe
...
# restore next_cursor_urlsafe

results = find_documents(query_string, 20,
                         search.Cursor(web_safe_string=next_cursor_urlsafe))

next_cursor用于什么?如何保存以及保存的目的是什么?我如何在第一时间获得光标?如果代码看起来像这样,使用memcache来保存还原光标?

class MainAdvIndexedPage(SearchBaseHandler):
    """Handles search requests for comments."""

    def get(self):
        """Handles a get request with a query."""
        regionname = 'Delhi'
        region = Region.all().filter('name = ', regionname).get()
        uri = urlparse(self.request.uri)
        query = ''
        if uri.query:
            query = parse_qs(uri.query)
            query = query['query'][0]
        # restore next_cursor_urlsafe
        next_cursor_urlsafe = memcache.get('results_cursor')
        if last_cursor:
            results = find_documents(query_string, 50,
                         search.Cursor(web_safe_string=next_cursor_urlsafe))
    results = find_documents(query, 50, search.Cursor())
        next_cursor = results.cursor    
        next_cursor_urlsafe = next_cursor.web_safe_string
        # save next_cursor_urlsafe
        memcache.set('results_cursor', results.cursor)
        template_values = {
            'results': results,'next_cursor':next_cursor,
            'number_returned': len(results.results),
            'url': url, 'user' : users.get_current_user(), 
            'url_linktext': url_linktext, 'region' : region, 'city' : '', 'request' : self.request, 'form' : SearchForm(), 'query' : query
        }
        self.render_template('indexed.html', template_values)

更新

从我从答案中看到的,我应该使用HTTP GET查询字符串来保存光标,但我仍然不确切知道如何。请告诉我怎么样。

更新2

这是我的新努力。

 def get(self):
    """Handles a get request with a query."""
    regionname = 'Delhi'
    region = Region.all().filter('name = ', regionname).get()

    cursor = self.request.get("cursor")

    uri = urlparse(self.request.uri)
    query = ''
    if uri.query:
        query = parse_qs(uri.query)
        query = query['query'][0]
    logging.info('search cursor: %s', search.Cursor())

    if cursor: 
        results = find_documents(query, 50, cursor)
    else:
       results = find_documents(query, 50, search.Cursor())
    next_cursor = None
    if results and results.cursor:
        next_cursor = results.cursor.web_safe_string
    logging.info('next cursor: %s', str(next_cursor))
    template_values = {
        'results': results,'cursor':next_cursor,
        'number_returned': len(results.results),
        'user' : users.get_current_user(), 
        'region' : region, 'city' : '', 'request' : self.request, 'form' : SearchForm(), 'query' : query
    }

我认为我已经理解它应该如何使用上面的内容,并且它在第一次命中时输出一个光标,所以我可以知道如何首先获得光标。这清楚地记录了很多。但是我收到此错误消息:cursor must be a Cursor, got unicode

1 个答案:

答案 0 :(得分:3)

不,你不应该使用memcache,尤其是使用像'results_cursor'这样的常量键 - 这意味着所有用户都会得到相同的游标,这将是不好的。

您已经将光标传递给模板上下文(尽管您应该像第二个示例中那样转换为web_safe_string)。在模板中,您应该确保光标字符串包含在“下一个”按钮的GET参数中:然后,在视图中,您应该从那里提取它并将其传递到find_documents调用中。

除了memcache问题,你几乎就是第二个例子了,但是你应该明确确保对find_documents的第二次调用是在else块内,所以它不会覆盖游标版本。