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

Есть ли вопрос где-то? Пожалуйста, уменьшите свой код до частей, чтобы поддержать ваш вопрос, и четко задайте вопрос. Благодарю. –

+0

Спасибо за то, что вы извинились за непонятный вопрос. Переписано, чтобы использовать пост/теги блога, чтобы сделать вопрос более ясным, а код был лишен, чтобы показывать только соответствующие аспекты. – CountZero

ответ

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

Смежные вопросы