/// <summary>
        /// Gets a page of videos for a search query.
        /// </summary>
        public async Task<VideosForSearchQuery> SearchVideos(SearchVideosQuery searchVideosQuery)
        {
            // Do a Solr query against DSE search to find videos using Solr's ExtendedDisMax query parser. Query the
            // name, tags, and description fields in the videos table giving a boost to matches in the name and tags
            // fields as opposed to the description field
            // More info on ExtendedDisMax: http://wiki.apache.org/solr/ExtendedDisMax
            string solrQuery = "{ \"q\": \"{!edismax qf=\\\"name^2 tags^1 description\\\"}" + searchVideosQuery.Query + "\" }";
            
            PreparedStatement prepared = await _statementCache.NoContext.GetOrAddAsync(
                "SELECT videoid, userid, name, preview_image_location, added_date FROM videos WHERE solr_query=?");

            // The driver's built-in paging feature just works with DSE Search Solr paging which is pretty cool
            IStatement bound = prepared.Bind(solrQuery)
                                       .SetAutoPage(false)
                                       .SetPageSize(searchVideosQuery.PageSize);

            // The initial query won't have a paging state, but subsequent calls should if there are more pages
            if (string.IsNullOrEmpty(searchVideosQuery.PagingState) == false)
                bound.SetPagingState(Convert.FromBase64String(searchVideosQuery.PagingState));

            RowSet rows = await _session.ExecuteAsync(bound).ConfigureAwait(false);
            
            return new VideosForSearchQuery
            {
                Query = searchVideosQuery.Query,
                Videos = rows.Select(MapRowToVideoPreview).ToList(),
                PagingState = rows.PagingState != null && rows.PagingState.Length > 0 ? Convert.ToBase64String(rows.PagingState) : null
            };
        }
 /// <summary>
 /// Gets a page of videos for a search query.
 /// </summary>
 public async Task<VideosForSearchQuery> SearchVideos(SearchVideosQuery searchVideosQuery)
 {
     // Do a Solr query against DSE search to find videos using Solr's ExtendedDisMax query parser. Query the
     // name, tags, and description fields in the videos table giving a boost to matches in the name and tags
     // fields as opposed to the description field
     // More info on ExtendedDisMax: http://wiki.apache.org/solr/ExtendedDisMax
     string solrQuery = "{ \"q\": \"{!edismax qf=\\\"name^2 tags^1 description\\\"}" + searchVideosQuery.Query + "\" }";
     
     // TODO: Update model to support paging with a cursor/token (DataStax driver now supports manual paging also)
     PreparedStatement prepared = await _statementCache.NoContext.GetOrAddAsync(
         "SELECT videoid, userid, name, preview_image_location, added_date FROM videos WHERE solr_query=? LIMIT ?");
     RowSet rows = await _session.ExecuteAsync(prepared.Bind(solrQuery, searchVideosQuery.PageSize));
     return new VideosForSearchQuery
     {
         Query = searchVideosQuery.Query,
         Videos = rows.Select(MapRowToVideoPreview).ToList()
     };
 }
        /// <summary>
        /// Gets a page of videos for a search query (looks for videos with that tag).
        /// </summary>
        public async Task<VideosForSearchQuery> SearchVideos(SearchVideosQuery searchVideosQuery)
        {
            // Use the driver's built-in paging feature to get only a page of rows
            PreparedStatement preparedStatement = await _statementCache.NoContext.GetOrAddAsync("SELECT * FROM videos_by_tag WHERE tag = ?");
            IStatement boundStatement = preparedStatement.Bind(searchVideosQuery.Query)
                                                         .SetAutoPage(false)
                                                         .SetPageSize(searchVideosQuery.PageSize);

            // The initial query won't have a paging state, but subsequent calls should if there are more pages
            if (string.IsNullOrEmpty(searchVideosQuery.PagingState) == false)
                boundStatement.SetPagingState(Convert.FromBase64String(searchVideosQuery.PagingState));

            RowSet rows = await _session.ExecuteAsync(boundStatement).ConfigureAwait(false);
            return new VideosForSearchQuery
            {
                Query = searchVideosQuery.Query,
                Videos = rows.Select(MapRowToVideoPreview).ToList(),
                PagingState = rows.PagingState != null && rows.PagingState.Length > 0 ? Convert.ToBase64String(rows.PagingState) : null
            };
        }
        /// <summary>
        /// Gets a page of videos for a search query (looks for videos with that tag).
        /// </summary>
        public async Task<VideosForSearchQuery> SearchVideos(SearchVideosQuery searchVideosQuery)
        {
            // If the first video id for the page was specified, use the query for a subsequent page, otherwise use the query for the first page
            PreparedStatement preparedStatement;
            IStatement boundStatement;
            if (searchVideosQuery.FirstVideoOnPageVideoId == null)
            {
                preparedStatement = await _statementCache.NoContext.GetOrAddAsync("SELECT * FROM videos_by_tag WHERE tag = ? LIMIT ?");
                boundStatement = preparedStatement.Bind(searchVideosQuery.Query, searchVideosQuery.PageSize);
            }
            else
            {
                preparedStatement = await _statementCache.NoContext.GetOrAddAsync("SELECT * FROM videos_by_tag WHERE tag = ? AND videoid >= ? LIMIT ?");
                boundStatement = preparedStatement.Bind(searchVideosQuery.Query, searchVideosQuery.FirstVideoOnPageVideoId.Value, searchVideosQuery.PageSize);
            }

            RowSet rows = await _session.ExecuteAsync(boundStatement).ConfigureAwait(false);
            return new VideosForSearchQuery
            {
                Query = searchVideosQuery.Query,
                Videos = rows.Select(MapRowToVideoPreview).ToList()
            };
        }