RavenDb学习(三)静态索引
在静态索引这块,RavenDb其实的是lucene,所以里面有很多概念,其实都是lucene本身的。 .定义静态Indexes documentStore.DatabaseCommands.PutIndex( "BlogPosts/PostsCountByTag", new IndexDefinitionBuilder<BlogPost, BlogTagPostsCount> { // The Map function: for each tag of each post, create a new BlogTagPostsCount // object with the name of a tag and a count of one. Map = posts => from post in posts from tag in post.Tags select new { Tag = tag, Count = }, // The Reduce function: group all the BlogTagPostsCount objects we got back // from the Map function, use the Tag name as the key, and sum up all the // counts. Since the Map function gives each tag a Count of 1, when the Reduce // function returns we are going to have the correct Count of posts filed under // each tag. Reduce = results => from result in results group result by result.Tag into g select new { Tag = g.Key, Count = g.Sum(x => x.Count) } }); public class BlogTagPostsCount { public string Tag { get; set; } public int Count { get; set; } } .索引层次化的数据 如下图中的数据,如果我们要索引Comments的话,应该如何索引 { //posts/123 'Name': 'Hello Raven', 'Comments': [ { 'Author': 'Ayende', 'Text': '...', 'Comments': [ { 'Author': 'Rahien', 'Text': '...', "Comments": [] } ] } ] } store.DatabaseCommands.PutIndex("SampleRecurseIndex", new IndexDefinition { Map = @"from post in docs.Posts from comment in Recurse(post, (Func<dynamic, dynamic>)(x => x.Comments)) select new { Author = comment.Author, Text = comment.Text }" }); 当然我们也可以定义一个类 public class SampleRecurseIndex : AbstractIndexCreationTask<Post> { public SampleRecurseIndex() { Map = posts => from post in posts from comment in Recurse(post, x => x.Comments) select new { Author = comment.Author, Text = comment.Text }; } } 然后创建new SampleRecurseIndex().Execute(store); .索引相关文档 )第一个例子 这个例子:Invoice和Customer,Invoice当中包含了Customer的Id ,现在我们要通过Customer的姓名来查询invoices public class Invoice { public string Id { get; set; } public string CustomerId { get; set; } } public class Customer { public string Id { get; set; } public string Name { get; set; } } public class SampleIndex : AbstractIndexCreationTask<Invoice> { public SampleIndex() { Map = invoices => from invoice in invoices select new { CustomerId = invoice.CustomerId, CustomerName = LoadDocument<Customer>(invoice.CustomerId).Name }; } } 建立完索引之后,我们就可以客户的名称来查询invoices了 )第二个例子 public class Book { public string Id { get; set; } public string Name { get; set; } } public class Author { public string Id { get; set; } public string Name { get; set; } public IList<string> BookIds { get; set; } } public class AnotherIndex : AbstractIndexCreationTask<Author> { public AnotherIndex() { Map = authors => from author in authors select new { Name = author.Name, Books = author.BookIds.Select(x => LoadDocument<Book>(x).Name) }; } } Author当中保存了所有的书的id,通过作者可以查询他出了多少书,通过书名页可以查到作者 这里面需要注意的是: )当相关文档变化的时候,索引也会变化 )使用LoadDocument 去跟踪一个文档,当多个文档跟踪同一个文档的时候,这会变成一个很耗费资源的开销 .TransformResults 有时候索引非常复杂,但是我们需要的数据比较简单,这个时候我们需要怎么做呢? public class PurchaseHistoryIndex : AbstractIndexCreationTask<Order, Order> { public PurchaseHistoryIndex() { Map = orders => from order in orders from item in order.Items select new { UserId = order.UserId, ProductId = item.Id }; TransformResults = (database, orders) => from order in orders from item in order.Items let product = database.Load<Product>(item.Id) where product != null select new { ProductId = item.Id, ProductName = product.Name }; } } 我们在查询的时候只需要PurchaseHistoryViewItem,这样子我们就用OfType来进行类型转换。 documentSession.Query<Shipment, PurchaseHistoryIndex>() .Where(x => x.UserId == userId) .OfType<PurchaseHistoryViewItem>() .ToArray(); .错误处理 当索引出现错误的时候,因为它是由一个后台线程执行的,索引我们很难发现的,通过查看'/stats'表或者 '/raven/studio.html#/statistics'或者'/raven/statistics.html'。 当错误超过15%的时候,索引就会被禁用掉,%的数量是在前10个文档之后统计的,为了防止一开始的文旦就不好使,就别禁用了。 下面是错误的一些信息,查看'/stats'得到的 { "LastDocEtag": "00000000-0000-0b00-0000-000000000001", "LastAttachmentEtag": "00000000-0000-0000-0000-000000000000", , , , "StaleIndexes": [], , , "Indexes":[ { "Name": "PostsByTitle", , , } ], "Errors":[ { "Index": "PostsByTitle", "Error": "Cannot perform runtime binding on a null reference", "Timestamp": "\/Date(1271778107096+0300)\/", "Document": "bob" } ] } .查询 在查询当中用 string.Contains()方式是会报错的,因为RavenDb不支持类似通配符*term*这样的方式,这样会引起性能问题,它会抛出NotSupportedException异常。 )多字段索引 documentStore.DatabaseCommands.PutIndex("UsersByNameAndHobbies", new IndexDefinition { Map = "from user in docs.Users select new { user.Name, user.Hobbies }", Indexes = { { "Name", FieldIndexing.Analyzed }, { "Hobbies", FieldIndexing.Analyzed } } }); )多字段查询 users = session.Query<User>("UsersByNameAndHobbies") .Search(x => x.Name, "Adam") .Search(x => x.Hobbies, "sport").ToList(); )相关性加速 通过设置相关性字段,可以减少一些不相关的内容搜索 users = session.Query<User>("UsersByHobbies") .Search(x => x.Hobbies, ) .Search(x => x.Hobbies, ).ToList(); 也可以在索引定义时候设定 public class Users_ByName : AbstractIndexCreationTask<User> { public Users_ByName() { this.Map = users => from user in users select new { FirstName = user.FirstName.Boost(), LastName = user.LastName }; } } )操作符 AND操作符 users = session.Query<User>("UsersByNameAndHobbiesAndAge") .Search(x => x.Hobbies, "computers") .Search(x => x.Name, "James") .Where(x => x.Age == ).ToList(); 上面的这一句也可以这么写 users = session.Query<User>("UsersByNameAndHobbies") .Search(x => x.Name, "Adam") .Search(x => x.Hobbies, "sport", options: SearchOptions.And).ToList(); NOT操作符 users = session.Query<User>("UsersByName") .Search(x => x.Name, "James", options: SearchOptions.Not).ToList(); 多操作符合作 并且不等于 users = session.Query<User>("UsersByNameAndHobbies") .Search(x => x.Name, "Adam") .Search(x => x.Hobbies, "sport", options: SearchOptions.Not | SearchOptions.And) .ToList(); )通配符,模糊查询 EscapeAll (default), AllowPostfixWildcard, AllowAllWildcards, RawQuery. users = session.Query<User>("UsersByName") .Search(x => x.Name, "Jo* Ad*", escapeQueryOptions:EscapeQueryOptions.AllowPostfixWildcard).ToList(); users = session.Query<User>("UsersByName") .Search(x => x.Name, "*oh* *da*", escapeQueryOptions: EscapeQueryOptions.AllowAllWildcards).ToList(); users = session.Query<User>("UsersByName") .Search(x => x.Name, "*J?n*", escapeQueryOptions: EscapeQueryOptions.RawQuery).ToList(); )高亮显示 public class SearchItem { public string Id { get; set; } public string Text { get; set; } } public class ContentSearchIndex : AbstractIndexCreationTask<SearchItem> { public ContentSearchIndex() { Map = (docs => from doc in docs select new { doc.Text }); Index(x => x.Text, FieldIndexing.Analyzed); Store(x => x.Text, FieldStorage.Yes); TermVector(x => x.Text, FieldTermVector.WithPositionsAndOffsets); } } //查询完毕之后进行处理 FieldHighlightings highlightings; var results = session.Advanced.LuceneQuery<SearchItem>("ContentSearchIndex") .Highlight(, , out highlightings) .Search("Text", "raven") .ToArray(); var builder = new StringBuilder() .AppendLine("<ul>"); foreach (var result in results) { var fragments = highlightings.GetFragments(result.Id); builder.AppendLine(string.Format("<li>{0}</li>", fragments.First())); } var ul = builder .AppendLine("</ul>") .ToString(); //查询时候设置前后符号 FieldHighlightings highlightings; var results = session.Advanced.LuceneQuery<SearchItem>("ContentSearchIndex") .Highlight(, , out highlightings) .SetHighlighterTags("**", "**") .Search("Text", "raven") .ToArray(); )推荐 下面是用户和基于用户名的索引 public class User { public string Id { get; set; } public string FullName { get; set; } } public class Users_ByFullName : AbstractIndexCreationTask<User> { public Users_ByFullName() { Map = users => from user in users select new { user.FullName }; Indexes.Add(x => x.FullName, FieldIndexing.Analyzed); } } 假设数据库里面存着以下数据: // users/1 { "Name": "John Smith" } // users/2 { "Name": "Jack Johnson" } // users/3 { "Name": "Robery Jones" } // users/4 { "Name": "David Jones" } 你使用了以下的查询语句 var query = session.Query<User, Users_ByFullName>().Where(x => x.FullName == "johne"); var user = query.FirstOrDefault(); 如果查询不到,可以使用推荐功能 if (user == null) { SuggestionQueryResult suggestionResult = query.Suggest(); Console.WriteLine("Did you mean?"); foreach (var suggestion in suggestionResult.Suggestions) { Console.WriteLine("\t{0}", suggestion); } } 它会给你推荐 john jones johnson 下面是包括全部参数的查询: session.Query<User, Users_ByFullName>() .Suggest(new SuggestionQuery() { Field = "FullName", Term = "johne", Accuracy = 0.4f, MaxSuggestions = , Distance = StringDistanceTypes.JaroWinkler, Popularity = true, }); 另外一种查询方式: store.DatabaseCommands.Suggest("Users/ByFullName", new SuggestionQuery() { Field = "FullName", Term = "johne" }); 多个关键词的推荐: 同时输入johne davi SuggestionQueryResult resultsByMultipleWords = session.Query<User, Users_ByFullName>() .Suggest(new SuggestionQuery() { Field = "FullName", Term = "<<johne davi>>", Accuracy = 0.4f, MaxSuggestions = , Distance = StringDistanceTypes.JaroWinkler, Popularity = true, }); Console.WriteLine("Did you mean?"); foreach (var suggestion in resultsByMultipleWords.Suggestions) { Console.WriteLine("\t{0}", suggestion); }
RavenDb学习(三)静态索引的更多相关文章
- Mongodb学习笔记三(Mongodb索引操作及性能测试)
第三章 索引操作及性能测试 索引在大数据下的重要性就不多说了 下面测试中用到了mongodb的一个客户端工具Robomongo,大家可以在网上选择下载.官网下载地址:http://www.robomo ...
- Android JNI学习(三)——Java与Native相互调用
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- Django基础学习三_路由系统
今天主要来学习一下Django的路由系统,视频中只学了一些皮毛,但是也做下总结,主要分为静态路由.动态路由.二级路由 一.先来看下静态路由 1.需要在project中的urls文件中做配置,然后将匹配 ...
- Spring Boot 项目学习 (三) Spring Boot + Redis 搭建
0 引言 本文主要介绍 Spring Boot 中 Redis 的配置和基本使用. 1 配置 Redis 1. 修改pom.xml,添加Redis依赖 <!-- Spring Boot Redi ...
- day 82 Vue学习三之vue组件
Vue学习三之vue组件 本节目录 一 什么是组件 二 v-model双向数据绑定 三 组件基础 四 父子组件传值 五 平行组件传值 六 xxx 七 xxx 八 xxx 一 什么是组件 首先给 ...
- Java入门学习路线目录索引
原创 Java入门学习路线目录索引 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/One_ ...
- Python基础学习三
Python基础学习三 1.列表与元组 len()函数:可以获取列表的元素个数. append()函数:用于在列表的最后添加元素. sort()函数:用于排序元素 insert()函数:用于在指定位置 ...
- ElasticSearch7.3学习(三十二)----logstash三大插件(input、filter、output)及其综合示例
1. Logstash输入插件 1.1 input介绍 logstash支持很多数据源,比如说file,http,jdbc,s3等等 图片上面只是一少部分.详情见网址:https://www.elas ...
- HTTP学习三:HTTPS
HTTP学习三:HTTPS 1 HTTP安全问题 HTTP1.0/1.1在网络中是明文传输的,因此会被黑客进行攻击. 1.1 窃取数据 因为HTTP1.0/1.1是明文的,黑客很容易获得用户的重要数据 ...
随机推荐
- MySQL,如何修改root帐户密码、如何解决root帐户忘记密码的问题
1. 如何修改root帐户密码 打开MySQL 5.6 Command Line Client窗口,输入当前密码登录,然后依次输入如下3条命令: use mysql; update user set ...
- Atitit 软件体系的进化,是否需要一个处理中心
Atitit 软件体系的进化,是否需要一个处理中心 1.1. 进化树上是没有主干的..1 1.2. ,软件进化的行为1::主要就是给新的应用编写新的程序.1 1.3. ,软件进化的行为2::软件的维护 ...
- 使用ASIHTTPRequest和ASIDownloadCache实现本地缓存
源码:http://files.cnblogs.com/ios8/ASIHttpRequestDemo2.zip NSURL *url = [NSURLURLWithString:@"htt ...
- 【Unity】7.6 自定义输入
分类:Unity.C#.VS2015 创建日期:2016-04-21 一.简介 在Unity中可以创建自定义的虚拟按键,然后将设备的输入映射到自定义的按键上.使用虚拟按键的好处是可以让游戏玩家自己定义 ...
- Gradle-修改.gradle默认目录
在Windows的环境变量中新建一个环境变量设置,GRADLE_USER_HOME,值为D:\Users\shaowei\.gradle,设置完成之后,点击确定,关闭设置窗口.这个时候可以去AS中看下 ...
- VS注释与取消注释快捷键
最近在使用VS2010开发ASP.Net,突然发现想全部注释时找不到注释的快捷键,网上查了下,原来很简单,只是需要使用组合键. 注释: 先CTRL+K,然后CTRL+C 取消注释: 先C ...
- 【Linux】Linux根目录下各文件夹的意义
[root@localhost /]# ll / total 102 dr-xr-xr-x. 2 root root 4096 Dec 1 07:37 bin # binary file,二进制执行文 ...
- Android 微信支付资料收集
老板要求支持微信支付,收集了些资料做后期参考 http://www.360doc.com/content/15/0214/10/7044580_448519997.shtml http://www.t ...
- Kafka: Connect
转自:http://www.cnblogs.com/f1194361820/p/6108025.html Kafka Connect 简介 Kafka Connect 是一个可以在Kafka与其他系统 ...
- Docker 入门(Mac环境)- part 4 swarms
part-4 Swarms 简介 这一节主要是介绍一下如何在集群模式下部署docker应用:集群的概念很好理解了,多台机器共同完成一项任务:和Hadoop那些集群一样,docker也相当于有一个管理机 ...