2012-04-06 12 views
26

Tôi biết các biến thể của câu hỏi này đã được hỏi trước (ngay cả tôi), nhưng tôi vẫn không hiểu một hay hai điều về ...Cách thích hợp để truy xuất hơn 128 tài liệu với RavenDB

It là sự hiểu biết của tôi rằng người ta có thể lấy tài liệu hơn các thiết lập 128 mặc định bằng cách làm này:

session.Advanced.MaxNumberOfRequestsPerSession = int.MaxValue; 

Và tôi đã học được rằng một mệnh đề WHERE phải là một ExpressionTree thay vì một Func, do đó nó được coi là queryable thay của Enumerable. Vì vậy, tôi nghĩ rằng điều này sẽ hoạt động:

public static List<T> GetObjectList<T>(Expression<Func<T, bool>> whereClause) 
{ 
    using (IDocumentSession session = GetRavenSession()) 
    { 
     return session.Query<T>().Where(whereClause).ToList();     
    } 
} 

Tuy nhiên, chỉ trả về 128 tài liệu. Tại sao?

Lưu ý, đây là mã mà gọi phương thức trên:

RavenDataAccessComponent.GetObjectList<Ccm>(x => x.TimeStamp > lastReadTime); 

Nếu tôi thêm Đưa (n), sau đó tôi có thể có được càng nhiều tài liệu như tôi muốn. Ví dụ, đây trả về 200 tài liệu:

return session.Query<T>().Where(whereClause).Take(200).ToList(); 

Dựa trên tất cả những điều này, nó sẽ có vẻ rằng cách thích hợp để lấy hàng ngàn tài liệu là để thiết lập và sử dụng MaxNumberOfRequestsPerSession Đưa() trong truy vấn. Có đúng không? Nếu không, làm thế nào nên nó được thực hiện?

Đối với ứng dụng của mình, tôi cần truy xuất hàng nghìn tài liệu (có rất ít dữ liệu trong đó). Chúng tôi giữ các tài liệu này trong bộ nhớ và được sử dụng làm nguồn dữ liệu cho biểu đồ.

** EDIT **

tôi đã cố gắng sử dụng int.MaxValue ở Đưa tôi():

return session.Query<T>().Where(whereClause).Take(int.MaxValue).ToList(); 

Và đó trả về 1024. Argh. Làm cách nào để nhận được nhiều hơn 1024?

** EDIT 2 - Mẫu văn bản hiển thị dữ liệu **

{ 
    "Header_ID": 3525880, 
    "Sub_ID": "120403261139", 
    "TimeStamp": "2012-04-05T15:14:13.9870000", 
    "Equipment_ID": "PBG11A-CCM", 
    "AverageAbsorber1": "284.451", 
    "AverageAbsorber2": "108.442", 
    "AverageAbsorber3": "886.523", 
    "AverageAbsorber4": "176.773" 
} 
+0

Bạn có nghĩ đến việc đặt tất cả 10000 điểm vào trong một tài liệu dưới dạng bộ sưu tập không? – SteadyEddi

Trả lời

20

Chức năng Take(n) sẽ chỉ cung cấp cho bạn lên đến 1024 theo mặc định. Tuy nhiên, bạn có thể thay đổi mặc định này trong Raven.Server.exe.config:

<add key="Raven/MaxPageSize" value="5000"/> 

Mọi chi tiết, xem: http://ravendb.net/docs/intro/safe-by-default

+0

Cảm ơn, Mike. Tôi nghĩ rằng điều này sẽ kết thúc là câu trả lời được chấp nhận, nhưng tôi muốn xem liệu có ai khác có một góc độ khác về điều này trước không. –

5

Số yêu cầu mỗi phiên là một khái niệm riêng biệt sau đó số lượng tài liệu lấy ra cho mỗi cuộc gọi. Các phiên họp ngắn ngủi và dự kiến ​​sẽ có ít cuộc gọi được phát hành qua chúng.

Nếu bạn đang nhận được nhiều hơn thì 10 của bất kỳ thứ gì từ cửa hàng (thậm chí ít hơn mặc định là 128) cho con người thì có gì đó không ổn hoặc vấn đề của bạn là yêu cầu suy nghĩ khác nhau sau đó tải các tài liệu đến từ kho dữ liệu.

Lập chỉ mục RavenDB khá phức tạp. Bài viết hay về lập chỉ mục here và các khía cạnh here.

Nếu bạn cần thực hiện tập hợp dữ liệu, hãy tạo chỉ mục bản đồ/giảm kết quả trong dữ liệu tổng hợp, ví dụ::

Index:

from post in docs.Posts 
    select new { post.Author, Count = 1 } 

    from result in results 
    group result by result.Author into g 
    select new 
    { 
     Author = g.Key, 
     Count = g.Sum(x=>x.Count) 
    } 

Query:

session.Query<AuthorPostStats>("Posts/ByUser/Count")(x=>x.Author)(); 
+1

Vậy bạn sẽ giải quyết vấn đề này như thế nào? Doanh nghiệp muốn xem biểu đồ hiển thị giá trị dữ liệu trong 24 giờ qua. Mỗi tài liệu là một điểm dữ liệu và có 10.000 trong số đó trong 24 giờ qua. Làm thế nào để bạn biểu đồ mà không mang tất cả dữ liệu? –

+0

Tôi nghĩ rằng bạn có thể đạt được điều này bằng cách tạo ra các chỉ mục hoặc [khía cạnh] (http://ravendb.net/docs/client-api/faceted-search) –

+0

Tôi chỉ nhận thấy "mỗi tài liệu là một điểm dữ liệu" - bạn có thể hiển thị một ví dụ về tài liệu này? –

16

Take (n) chức năng sẽ chỉ cung cấp cho bạn lên đến 1024 theo mặc định. Tuy nhiên, bạn có thể sử dụng nó trong cặp với Skip (n) để có được tất cả

 var points = new List<T>(); 
     var nextGroupOfPoints = new List<T>(); 
     const int ElementTakeCount = 1024; 
     int i = 0; 
     int skipResults = 0; 

     do 
     { 
      nextGroupOfPoints = session.Query<T>().Statistics(out stats).Where(whereClause).Skip(i * ElementTakeCount + skipResults).Take(ElementTakeCount).ToList(); 
      i++; 
      skipResults += stats.SkippedResults; 

      points = points.Concat(nextGroupOfPoints).ToList(); 
     } 
     while (nextGroupOfPoints.Count == ElementTakeCount); 

     return points; 

RavenDB Paging

+1

Phương pháp này là cho đến nay cách tiếp cận tốt hơn. – Matt

+4

Hãy coi chừng giới hạn về số lượng yêu cầu máy chủ. Theo cài đặt "an toàn theo mặc định" của Raven, nó sẽ chỉ thực hiện tối đa 30 chuyến đi vòng quanh máy chủ, vì vậy nếu vòng lặp cần thực thi nhiều hơn, nó sẽ thất bại vì mỗi lần lặp của vòng lặp là một yêu cầu máy chủ khác. –

34

Điều đáng chú ý là kể từ phiên bản 2.5, RavenDB có một "kết quả không giới hạn API" để cho phép streaming. Ví dụ từ tài liệu cho biết cách sử dụng:

var query = session.Query<User>("Users/ByActive").Where(x => x.Active); 
using (var enumerator = session.Advanced.Stream(query)) 
{ 
    while (enumerator.MoveNext()) 
    { 
     User activeUser = enumerator.Current.Document; 
    } 
} 

Có hỗ trợ cho truy vấn RavenDB chuẩn, truy vấn Lucence và cũng có hỗ trợ không đồng bộ.

Tài liệu có thể được tìm thấy here. Bài viết blog giới thiệu của Ayende có thể được tìm thấy here.

+1

+1 cho mẹo. Cảm ơn! –

+3

Cảnh giác rằng khi truy vấn bằng cách sử dụng API Streaming, chỉ mục phải tồn tại. Nếu bạn chạy truy vấn thông qua API phiên bình thường và không có chỉ mục phù hợp nào tồn tại, chỉ mục động sẽ được tạo. Nhưng trong API truyền trực tuyến, chỉ mục động không được tạo và máy chủ than phiền rằng chỉ mục không được tìm thấy. –

+0

Mike - đó là hành vi thú vị, nó có vẻ giống như một con bọ. Bạn đã thảo luận điều này trong nhóm RavenDB chưa? –

0

Bạn cũng có thể sử dụng chỉ mục được xác định trước với phương pháp Stream. Bạn có thể sử dụng mệnh đề Where trên các trường được lập chỉ mục.

var query = session.Query<User, MyUserIndex>(); 
var query = session.Query<User, MyUserIndex>().Where(x => !x.IsDeleted); 

using (var enumerator = session.Advanced.Stream<User>(query)) 
{ 
    while (enumerator.MoveNext()) 
    { 
     var user = enumerator.Current.Document; 
     // do something 
    } 
} 

Ví dụ chỉ số:

public class MyUserIndex: AbstractIndexCreationTask<User> 
{ 
    public MyUserIndex() 
    { 
     this.Map = users => 
      from u in users 
      select new 
      { 
       u.IsDeleted, 
       u.Username, 
      }; 
    } 
} 

Tài liệu: What are indexes? Session : Querying : How to stream query results?


Lưu ý quan trọng: phương pháp Stream sẽ không theo dõi các đối tượng. Nếu bạn thay đổi các đối tượng thu được từ phương pháp này, SaveChanges() sẽ không nhận thức được bất kỳ thay đổi nào.


Lưu ý khác: bạn có thể nhận được ngoại lệ sau nếu bạn không chỉ định chỉ mục sử dụng.

InvalidOperationException: StreamQuery không hỗ trợ truy vấn chỉ mục động. Nó được thiết kế để được sử dụng với các tập dữ liệu lớn và không thể trả về tất cả các tập dữ liệu sau 15 giây lập chỉ mục, như Query().