2013-05-07 53 views
1

我希望能夠帶回所有包含我指定的所有標籤的博客文章。RavenDB - 用多個詞條查詢集合

public class Post 
{ 
    public int Name { get; set; } 
    public List<string> Tags { get; set; } 
} 

我想帶'c#'和'html'標籤帶回所有帖子。

這個問題和我的一樣,雖然我無法讓我的例子工作。 Linq query with multiple Contains/Any for RavenDB

我想知道爲什麼下面的例子沒有帶回任何結果,當標籤中有'c#'和'html'的帖子時。

這將是巨大的,如果任何人都可以。如果現在有解決這個問題的一個新的,更優雅的方式闡明,理想與強類型的查詢語法即

var query = s.Query<Entity, IndexClass>() 

-

using System.Collections.Generic; 
using System.Linq; 
using NUnit.Framework; 
using Raven.Abstractions.Indexing; 
using Raven.Client.Embedded; 
using Raven.Client.Indexes; 

namespace RavenDB 
{ 
    public class Blog 
    { 
     public string Name { get; set; } 
     public List<string> Tags { get; set; } 
    } 

    public class BlogsByTags : AbstractIndexCreationTask<Blog> 
    { 
     public BlogsByTags() 
     { 
      Map = docs => from doc in docs 
          select new 
           { 
            Tags = doc.Tags 
           }; 

      Index(x => x.Tags, FieldIndexing.Analyzed); 
     } 
    } 

    [TestFixture] 
    public class Runner : UsingEmbeddedRavenStore 
    { 
     [Test] 
     public void Run() 
     { 
      Open(); 
      IndexCreation.CreateIndexes(typeof(BlogsByTags).Assembly, Store); 

      var blogs = new List<Blog> 
       { 
        new Blog{Name = "MVC", Tags = new List<string>{"html","c#"}}, 
        new Blog{Name = "HTML5", Tags = new List<string>{"html"}}, 
        new Blog{Name = "Version Control", Tags = new List<string>{"git"}}, 
       }; 

      using (var session = Store.OpenSession()) 
      {    
       foreach (var blog in blogs) 
       { 
        session.Store(blog); 
       } 
       session.SaveChanges(); 
      } 

      var tags = new List<string> { "c#", "html" }; 

      List<Blog> blogQueryResults; 

      using (var s = Store.OpenSession()) 
      { 

       blogQueryResults = s.Advanced.LuceneQuery<Blog, BlogsByTags>() 
        .Where(string.Format("Tags:({0})", string.Join(" AND ", tags))).ToList();     
      } 

      Assert.AreEqual(1, blogQueryResults.Count()); 
     } 
    } 

    public abstract class UsingEmbeddedRavenStore 
    { 
     protected EmbeddableDocumentStore Store { get; set; } 

     protected void Open() 
     { 
      Store = new EmbeddableDocumentStore 
      { 
       RunInMemory = 
        true 
      }; 

      Store.Initialize(); 
     } 

     protected void Dispose() 
     { 
      Store.Dispose(); 
     } 
    } 
} 
+0

在那裏有問題嗎?請將您的代碼減少到僅支持您的問題的部分,並清楚地詢問問題。謝謝。 – 2013-05-07 14:35:49

+0

感謝您對不清楚的問題表示歉意。重新編寫使用博客文章/標籤,使問題更清晰,代碼已被剝離,只顯示相關方面。 – CountZero 2013-05-07 22:14:29

回答

4

唯一的問題是,由於您在單元測試中,因此您需要明確允許在寫入數據和檢查索引之間的時間。否則,你的索引是陳舊的。請參閱these docs

s.Advanced.LuceneQuery<Blog, BlogsByTags>() 

// Unit tests should wait explicitly. 
// Don't do this outside of a unit test. 
.WaitForNonStaleResults() 

.Where(string.Format("Tags:({0})", string.Join(" AND ", tags))) 

您還問過如何執行相同的查詢,而不訴諸高級lucene語法。您可以使用的.Search擴展方法,因爲這樣的:

s.Query<Blog, BlogsByTags>() 
.Customize(x => x.WaitForNonStaleResults()) 
.Search(x => x.Tags, string.Join(" AND ", tags)) 

有你應該改變一兩件事。當單元測試時,你真的不希望單元測試正在掃描程序集的索引。它可能會爲其他測試編寫索引。

// Instead of scanning like this 
IndexCreation.CreateIndexes(typeof(BlogsByTags).Assembly, store); 

// Create the single index like this 
store.ExecuteIndex(new BlogsByTags()); 

最後,我想指出RavenDB.Tests.Helpers NuGet包,你可以用它來簡化你的測試。它爲你做了很多設置工作。它雖然使用了XUnit,所以如果你和NUnit綁定,那麼你可能想按自己的方式做事。

+0

感謝您的詳細回覆。 – CountZero 2013-05-08 09:49:17