2013-05-07 98 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