Skip to main content
 首页 » 编程设计

c#之RavenDB之查询具有多个术语的集合

2024年02月13日29tuyile006

我希望能够恢复所有具有我指定的所有标签的博文。

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(); 
        } 
    } 
} 

请您参考如下方法:

唯一的问题是,由于您正在进行单元测试,因此您需要在写入数据和检查索引之间明确留出时间。否则,您的索引已过时。参见 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,那么您可能想按照自己的方式做事。