RavenDB -查询包含多个词项的集合

本文关键字:集合 查询 包含多 RavenDB | 更新日期: 2023-09-27 18:12:41

我希望能够带回所有具有我指定的所有标签的博客文章。

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

我想把所有带有'c#'和'html'标签的帖子带回来。

这个问题和我的一样,虽然我不能让我的例子工作。包含多个Contains/Any的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();
        }
    }
}

RavenDB -查询包含多个词项的集合

唯一的问题是,由于您处于单元测试中,因此需要显式地允许在写入数据和检查索引之间的时间间隔。否则,索引就过时了。

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,你可能想用你自己的方式来做。