1

我希望能够恢复所有包含我指定的所有标签的博客文章。

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

我想带回所有带有“c#”和“html”标签的帖子。

这个问题和我的一样,虽然我无法让我的例子工作。 具有多个包含/任何用于 RavenDB 的 Linq 查询

我想知道为什么当标签中有一篇带有“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();
        }
    }
}
4

1 回答 1

4

唯一的问题是,由于您处于单元测试中,因此您需要明确地在数据写入和检查索引之间留出时间。否则,您的索引是陈旧的。请参阅这些文档

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 相关,那么你可能想要以自己的方式做事。

于 2013-05-07T23:36:56.043 回答