def search_and_sort(conn, query, id=None, ttl=300, sort="-updated", 
                    start=0, num=20):                              
    # 决定基于文章的哪个属性进行排序，以及是进行升序排序还是降序排序。
    desc = sort.startswith('-')                                   
    sort = sort.lstrip('-')                                       
    by = "kb:doc:*->" + sort                                      
    # 告知 Redis ，排序是以数值方式进行还是字母方式进行。
    alpha = sort not in ('updated', 'id', 'created')               

    # 如果用户给定了已有的搜索结果，
    # 并且这个结果仍然存在的话，
    # 那么延长它的生存时间。
    if id and not conn.expire(id, ttl):    
        id = None                         

    # 如果用户没有给定已有的搜索结果，
    # 或者给定的搜索结果已经过期，
    # 那么执行一次新的搜索操作。
    if not id:                                      
        id = parse_and_search(conn, query, ttl=ttl) 

    pipeline = conn.pipeline(True)
    # 获取结果集合的元素数量。
    pipeline.scard('idx:' + id)                                     
    # 根据指定属性对结果进行排序，并且只获取用户指定的那一部分结果。
    pipeline.sort('idx:' + id, by=by, alpha=alpha,                 
        desc=desc, start=start, num=num)                            
    results = pipeline.execute()

    # 返回搜索结果包含的元素数量、搜索结果本身以及搜索结果的 ID ，
    # 其中搜索结果的 ID 可以用于在之后再次获取本次搜索的结果。
    return results[0], results[1], id                             
# <end id="sorted-searches"/>


# 代码清单 7-6
# <start id="zset_scored_composite"/>
# 和之前一样，函数接受一个已有搜索结果的 ID 作为可选参数，
# 以便在结果仍然可用的情况下，对其进行分页。
dataset/ETHPy150Open huangz1990/riacn-code/ch07_listing_source.py/search_and_sort/original