2008年8月6日

stringTemplate是一个模板引擎,同时支持java,C#,Python. 大家可以从http://www.stringtemplate.org/下载.
StringTemplate 语法说明

StringTemplate的语法是以$xxxx$来进行分割的. stringtemplate关键写是区分大小写的.

属性引用
名称属性
在模板中,这个是最常用的一个属性.用于显示文字.如下:

你的邮件地址:$email$

替换属性名为email的值.

同一个属性可以有多个值,多个值的语法如下
$value;null="xxx",separator=", "$
定义value属性,当value为null则显示xxx.如果有多个属性值则以,号分开

字段引用
如果一个属性名称是对象或集合.可以用 属性名称.字段名 访问字段值
例如:
你的姓名: $人.姓名$
你的邮件:$人.邮件$

使用语法: $对象名.字段名$
在C#可以直接将一个对象设置到一个属性名称中.
如:
User us = new User();
us.Name = "xxsssx";
us.Value ="80";

StringTemplate st = new StringTemplate("$User.Name$,$User.Value$");
st.SetAttribute("User", us);

Console.WriteLine(st.ToString());
对于键/值对象,也同样使用上面方式进行访问如:
StringTemplate a = new StringTemplate("$user.name$, $user.phone$");
Hashtable user = new Hashtable();
user.Add("name", "Terence");
user.Add("phone", "none-of-your-business");
a.SetAttribute("user", user);
string results = a.ToString();


自定义属性字段名
格式: $属性名:{it.字段名}$
例如:
StringTemplate st = new StringTemplate("$abcdef:{第一个: $it.ddddd$ 第二个:$it.ddddd$}$");
st.SetAttribute("abcdef.{ddddd,ddddd}","中国人", "我不来了");
Console.WriteLine(st.ToString());

如果字段名是保留字,可以使用$对象名.("保留字")$

一次显示多个属性
$[属性名,属性名]$


模板引用
必需把模板加入同一个模板组,才能相互之间调用模板.
通过$模板名()$来调用模板
模板传参数
$模板名(参数名=参数值,参数名=参数值)$
例如:
StringTemplateGroup Group = new StringTemplateGroup("Temp");
Group.DefineTemplate("link", "<a href='$url$'>$title$</a>");
StringTemplate st = new StringTemplate(Group, "调用link模板,显示链接 $link(url=\"/faq/view?ID=\"+faqid, title=faqtitle)$ ,真的啊!");
st.SetAttribute("faqid", 1);
st.SetAttribute("title","中华人民共和国");
Console.WriteLine(st.ToString());

循环显示使用
User us = new User();
us.Name = "哈哈";
us.Value = "99";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
uss.Add(us);
StringTemplate st = new StringTemplate("<table>$User:{<tr>$it.Name$<td></td>$it.Value$</tr>}$</table>");
st.SetAttribute("User", uss);
Console.WriteLine(st.ToString());

通过模板交替显示
StringTemplateGroup group = new StringTemplateGroup("Test");
group.DefineTemplate("TrRed", "<tr class=red><td>$it.name$</td><td>$it.value$</td></tr>\n");
group.DefineTemplate("TrWither", "<tr class=wither><td>$it.name$</td><td>$it.value$</td></tr>\n");

StringTemplate st = new StringTemplate(group, "<table>$User:TrRed(),TrWither()$</table>");
User us = new User();
us.Name = "哈哈哈";
us.Value = "999";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
st.SetAttribute("User", uss);
Console.WriteLine(st.ToString());

例子教程下载:下载

附:英文语法介绍

Syntax

Description

<attribute>

Evaluates to the value of attribute.ToString() if it exists else empty string.

<i>, <i0>

The iteration number indexed from one and from zero, respectively, when referenced within a template being applied to an attribute or attributes.

<attribute.property>

Looks for property of attribute as a property (C#), then accessor methods like getProperty() or isProperty(). If that fails, StringTemplate looks for a raw field of the attribute called property. Evaluates to the empty string if no such property is found.

<attribute.(expr)>

Indirect property lookup. Same as attribute.property except use the value of expr as the property_ name. Evaluates to the empty string if no such property is found.

<multi-valued-attribute>

Concatenation of ToString() invoked on each element. If multi-valued-attribute is missing his evaluates to the empty string.

<multi-valued-attribute; separator=expr>

Concatenation of ToString() invoked on each element separated by expr.

<template(argument-list)>

Include template. The argument-list is a list of attribute assignments where each assignment is of the form arg-of-template=expr where expr is evaluated in the context of the surrounding template
not of the invoked template.

<(expr)(argument-list)>

Include template whose name is computed via expr. The argument-list is a list of attribute assignments where each assignment is of the form attribute=expr. Example $(whichFormat)()$ looks up whichFormat's value and uses that as template name. Can also apply an indirect template to an attribute.

<attribute:template(argument-list)>

Apply template to attribute. The optional argument-list is evaluated before application so that you can set attributes referenced within template. The default attribute it is set to the value of attribute. If attribute is multi-valued, then it is set to each element in turn and template is invoked n times where n is the number of values in attribute. Example: $name:bold() applies bold() to name's value.

<attribute:(expr)(argument-list)>

Apply a template, whose name is computed from expr, to each value of attribute. Example $data:(name)()$ looks up name's value and uses that as template name to apply to data.

<attribute:t1(argument-list): ... :tN(argument-list)>

Apply multiple templates in order from left to right. The result of a template application upon a multi-valued attribute is another multi-valued attribute. The overall expression evaluates to the concatenation of all elements of the final multi-valued attribute resulting from templateN's application.

<attribute:{anonymous-template}>

Apply an anonymous template to each element of attribute. The iterated it atribute is set automatically.

<attribute:{argument-name_ | _anonymous-template}>

Apply an anonymous template to each element of attribute. Set the argument-name to the iterated value and also set it.

<a1,a2,...,aN:{argument-list_ | _anonymous-template}>

Parallel list iteration. March through the values of the attributes a1..aN, setting the values to the arguments in argument-list in the same order. Apply the anonymous template. There is no defined it value unless inherited from an enclosing scope.

<attribute:t1(),t2(),...,tN()>

Apply an alternating list of templates to the elements of attribute. The template names may include argument lists.

<if(attribute)>subtemplate
<else>subtemplate2
<endif>

If attribute has a value or is a bool object that evaluates to true, include subtemplate else include subtemplate2. These conditionals may be nested.

<if(!attribute)>subtemplate<endif>

If attribute has no value or is a bool object that evaluates to false, include subtemplate. These conditionals may be nested.

<first(attr)>

The first or only element of attr. You can combine operations to say things like first(rest(names)) to get second element.

<last(attr)>

The last or only element of attr.

<rest(attr)>

All but the first element of attr. Returns nothing if $attr$ a single valued.

<strip(attr)>

Returns an iterator that skips any null values in $attr$. strip
=x when x is a single-valued attribute.

<length(attr)>

Return an integer indicating how many elements in length $attr$ is. Single valued attributes return 1. Strings are not special; i.e., length("foo") is 1 meaning "1 attribute". Nulls are counted in lists so a list of 300 nulls is length 300. If you don't want to count nulls, use length(strip(list)).

\$ or \<

escaped delimiter prevents $ or < from starting an attribute expression and results in that single character.

<\ >, <\n>, <\t>, <\r>

special characters: space, newline, tab, carriage return.

<! comment !>, $! comment !$

Comments, ignored by StringTemplate

posted @ 2008-08-06 11:01 隨風.NET 阅读(33) | 评论 (0)编辑

2008年8月3日

  1. 把资源文件的生成操作设为嵌入的资源
  2. 然后将下面这行
    [assembly: WebResource("NPao.Control.Resource.DateDropDownList.js", "text/javascript")]
    添加到在assemblyinfo.cs中。其实这个语句放任何cs文件里,保证放在最高级namespace外就行
    DateDropDownList.js是资源名字,比如项目的Default namespace是“NPao.Control”,
    而文件DateDropDownList.js放在/Resource目录中,那么完整资源名就是NPao.Control.Resource.DateDropDownList.js
    1. 然后在程序中调用如下:
    1. Image1.ImageUrl =  this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "wuChang.WebControls.images.MessagePanel_info.gif");
  • posted @ 2008-08-03 21:45 隨風.NET 阅读(25) | 评论 (0)编辑

    2008年7月16日

         摘要: 最近在重构公司的电子商务网站,其中有个打折消费的功能.这里简单介绍下,比如,网站搞活动买二送一(以下称A),或者买二瓶其中价格低的一瓶半价(以下称B),.最初的设计是很粗糙的,因为之前网站是没有活动,后来增加一个活动,现在又要增加新的活动.从一开始的直接写代码,到后来的if else 判断打折条件,到现在又要添加新的打折,觉得这样的代码写的很粗糙,有种不爽的感觉.现在刚好有机会重构这里,就大概设计... 阅读全文
    posted @ 2008-07-16 10:55 隨風.NET 阅读(89) | 评论 (0)编辑

    2008年7月6日

    1. 什么是对象?对象是一个自包含的实体,用一组可识别的特性和行为来标识.
    2. 什么是类? 类是具有相同属性和功能的对象的抽象的集合.
    3. 什么是实例?实例就是一个真实的对象.实例化就是创建对象的过程,用new关键字来创建.new关键字用来在内存中申请一个空间存放数据.
    4. 构造函数 默认一个无参数的构造函数,在new class的时候调用
    5. 方法重载 可在不改变原方法的基础上增加功能,方法名相同,参数类型或个数有所不同
    6. 字段是存储类要满足其设计所需要的数据,是与类相关的变量
    7. 属性是一个方法,但在调用他们的代码看来他是一个字段,属性适合以字段的方式使用方法调用的场合(使用属性可以设置符合要求的的字段的值)
    8. Public 允许任何类访问 private 仅允许同一个类的成员访问,他的子类也不能访问,定义变量时默认为private,protected的子类可以访问基类
    9. 封装:每个对象都包含它能进行操作所需要的所有信息,因此对象不必依赖其他对象来完成自己的操作 好处,减少耦合,内部可自由修改,具有清晰的对外接口
    10. 继承代表了一种 "is-a"的关系,还可以理解为是对被继承者的特殊化,除了具备被继承者的特性外,还具备有自己的独有个性,他定义类之间如何关联共享.
      1. 子类拥有父类非private的属性和功能
      2. 子类可以扩展父类没有的属性和功能
      3. 子类还可以以自己的方式实现父类的功能(方法重写)
      4. 子类不能继承基类的构造方法,只能被调用,可以使用base关键词
      5. 继承使得所有子类公共的部分都放在了父类,使得代码得到共享,避免重复
      6. 使得修改或扩展变得容易
      7. 缺点,父类变则子类不得不变,破坏封装,父类实现的细节暴露给子类
      8. 强耦合的关系,当2个类具备is-a的关系时,就可以考虑用继承
    11. 多态表示不同的对象可以执行相同的操作,但要通过他们自己的实现代码执行
      1. 子类以父类的身份出现
      2. 子类工作的时候以自己的方式来实现
      3. 子类以父类的身份出现的时候,子类特有的属性和方法不可以再使用
    12. 虚方法 virtual 为了让子类的实例完全接替来自父类的类成员,父类必须将该成员声明称虚拟的, 虚方法是按照运行时类型而非编译时类型进行动态绑定调用
    13. 子类可以选择使用override关键字,来实现替换父类的实现,方法重写
    14. 抽象类
      1. 类和方法前加上abstract,即抽象类和抽象方法
      2. 抽象类不能实例化
      3. 抽象方法是必须被子类重写的方法
      4. 如果类中包含有抽象方法,那么类就必须定义为抽象类,不论是否还包含有其他一般方法
      5. 抽象类拥有尽可能多的共同代码,拥有尽可能少的数据
      6. 抽象类通常代表一个抽象概念,他提供一个继承的出发点,当设计一个新的抽象类时,一定是用来继承的.
    15. 接口是把隐式公共方法和属性组合起来,以封装特定功能的一个集合
      1. 实现接口类就必须实现接口中的所以方法和属性
      2. 一个类可以实现多个接口
      3. 接口中的方法或属性前面不能有修饰符,方法没有方法体
    16. 抽象类与接口的区别
      1. 抽象类可以给出一些成员的实现,接口却不包含成员的实现
      2. 抽象类中的成员可以被子类实现,而接口的成员需要类完成实现
      3. 一个类只能继承一个抽象类,而可以接受多个接口
      4. 类是对对象的抽象,抽象类是对类的抽象,接口是对行为的抽象
      5. 如果行为跨越不同类的对象,可使用接口,对于一些相似的类对象,用继承抽象类
      6. 从设计角度讲,抽象类是从子类中发现了公共的东西,泛化出父类,然后子类继承父类,而接口是根本不知道子类的存在,方法如何实现还不确认,预先定义
      7. 通过重构改善既有代码设计
    17. 泛型是具有占位符的类接口结构和方法
      1. 使用泛型不需要装箱拆箱
    18. 委托与事件
      1. 委托是对函数的封装,可以当作给方法的特征指定一个名称.而事件是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程
      2. 委托是一种引用方法的类型,一旦为委托分配了方法,委托将与方法具有相同的行为
      3. 在发生其他类或对象关注的事情时,类或对象可通过事件通知他们
    posted @ 2008-07-06 11:31 隨風.NET 阅读(32) | 评论 (0)编辑

    2008年7月4日

     

    测试

    posted @ 2008-07-04 14:52 隨風.NET 阅读(23) | 评论 (0)编辑

    2008年7月1日

        最近买了园子里一位大哥出的书,大话设计模式,之前也买过园子里的几本书,比如设计之道,道不远人等,怎么发现里面都有个道字

        道不远人也是刚刚到手,还没来得及看,大话设计模式已经由当当送出.

        2本书拿到手上一比,道不远人那个厚啊,还是先从薄的开始看起吧^^

        话说好记性不如烂笔头,之前看过很多书,当时看了现在就忘了,要记录下点学习笔记了,这个是开篇,要逐步记录下读书笔记

        看看自己有没毅力哈
    posted @ 2008-07-01 09:52 隨風.NET 阅读(31) | 评论 (0)编辑

    2008年6月25日

         最近要给公司的电子商务网站添加个圈子的功能.网站功能本来就包含有新闻发布,会员管理,商品购物,后台管理等,现在又要再加上圈子的功能,网站项目越来越复
    杂,每次编译生成的dll超过100k.这样每次修改任何一个功能中的任何一个小问题都要上传整个dll,并导致整个website的首次访问的重新编译.
         之前也曾经想过,这些功能根据不同处于项目中的不同文件夹内,比如会员的会在member,后台管理的会在admin文件夹,新闻的会在news文件夹.这样的话如果vs支持按不同文件夹生成不同dll,那我每次修改不同功能的不同文件只要上传对应的dll就可以了,不再需要上传整个website的dll.
         不过想法是美好的,事实是残酷的.vs并不支持这样的功能.所以在功能直接交互和文件共享并不多的功能上,我采取了重新建立一个projects的方法,比如把后台管理剥离出来,新建一个admin的website,这个新的projects放在website的根目录下,然后修改文件编译生成dll后的目录为..\bin并且删除项目中的web.config.编译后访问,呵呵,真的可以访问了,并且达到了拆分项目的要求.倒是并不完美,还有手动修改很多设置,并且这2个项目中不能共享相同的master,和usercontrol,甚至是图片,js等,如果直接使用相对路径,那么视图模式下将不能正常显示,如果vs直接提供新建子项目的功能并能解决共享这些文件,该有多好啊.
         于是通过Google,找到一篇文章http://blogs.msdn.com/webdevtools/archive/2006/07/01/652986.aspx,Creating sub-projects in IIS with Web Application Projects,不幸的是文中提到的“Web Application Projects” add-in,我Download了,but can't install!
         虽然这样的应用程序我们无法制作,但是我们可以按照他的思路自己修改配置啊.
         发现他的方法,跟一开始我的做法是很类似的,不过他可以共享master和user control,为什么我的不能呢?
         仔细翻看了一下,发现原来他在子项目中创建了虚拟目录比如 http://localhost/group,所以之前使用~/Group.Master,只能访问本项目中的master,而现在则可以访问根目录中的master了,试试usercontrol,也可以了,呵呵,原理奥妙都在这个虚拟目录中呀.
         不过最后,还是觉得这样的方式不是很舒服,不知道大家有没什么好的办法,我在这里抛下砖.

          本来想发在新手区的,但是我觉得这个应该是大部分程序员都会遇到的问题,把Web 应用程序分解为多个较小项目也有很多优点,不知道各位达人平时如何解决的?
    如果大家觉得放在首页不合适的话,我也会移开.

    posted @ 2008-06-25 11:25 隨風.NET 阅读(1866) | 评论 (20)编辑

    2008年5月29日

           本以为蜘蛛很简单,根据一个url,抓取到html内容,然后根据正则匹配数据入库.却发现,越看资料越复杂,蜘蛛应该根据抓取相似页面自动生成抓取模板,而且蜘蛛还要支持cookies和会自登录等多种协议.
            页面解析方面,也不是简单的获得标题和内容那么简单,还要做dom解析,js解析,模拟浏览器的可视化抓取等等.
            先从页面数据的抽取这方面入手研究吧.
    posted @ 2008-05-29 10:31 隨風.NET 阅读(46) | 评论 (0)编辑

    2008年5月27日

    本文仅记录一些简单的使用方法,供初学者参考。
    以下例子采用 Lucene.NET 1.9 版本,可取去 Lucene.Net 下载。

    1. 基本应用

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Lucene.Net;
    using Lucene.Net.Analysis;
    using Lucene.Net.Analysis.Standard;
    using Lucene.Net.Documents;
    using Lucene.Net.Index;
    using Lucene.Net.QueryParsers;
    using Lucene.Net.Search;
    using Lucene.Net.Store;
    using Lucene.Net.Util;

    namespace ConsoleApplication1.Lucene
    {
      public class LuceneTest
      {
        private const string FieldName = "name";
        private const string FieldValue = "value";

        private Directory directory = new RAMDirectory();
        private Analyzer analyzer = new StandardAnalyzer();

        public LuceneTest()
        {
        }

        private void Index()
        {
          IndexWriter writer = new IndexWriter(directory, analyzer, true);
          writer.maxFieldLength = 1000;
          
          for (int i = 1; i <= 100; i++)
          {
            Document document = new Document();

            document.Add(new Field(FieldName, "name" + i, Field.Store.YES, Field.Index.UN_TOKENIZED));
            document.Add(new Field(FieldValue, "Hello, World!", Field.Store.YES, Field.Index.TOKENIZED));

            writer.AddDocument(document);
          }

          writer.Optimize();
          writer.Close();
        }

        private void Search()
        {
          Query query = QueryParser.Parse("name*", FieldName, analyzer);

          IndexSearcher searcher = new IndexSearcher(directory);

          Hits hits = searcher.Search(query);
          
          Console.WriteLine("符合条件记录:{0}; 索引库记录总数:{1}", hits.Length(), searcher.Reader.NumDocs());
          for (int i = 0; i < hits.Length(); i++)
          {
            int docId = hits.Id(i);
            string name = hits.Doc(i).Get(FieldName);
            string value = hits.Doc(i).Get(FieldValue);
            float score = hits.Score(i);

            Console.WriteLine("{0}: DocId:{1}; Name:{2}; Value:{3}; Score:{4}", 
              i + 1, docId, name, value, score);
          }

          searcher.Close();
        }
      }
    }

    除了 RAMDirectory,还可以使用 FSDirectory。(注意 FSDirectory.GetDirectory 的 create 参数,为 true 时将删除已有索引库文件,可以通过 IndexReader.IndexExists() 方法判断。)

    从指定目录打开已有索引库。
    private Directory directory = FSDirectory.GetDirectory("c:\index", false);

    将索引库载入内存,以提高搜索速度。
    private Directory directory = new RAMDirectory(FSDirectory.GetDirectory(@"c:\index", false));
    //或
    //private Directory directory = new RAMDirectory(c:\index");

    2. 多字段搜索

    使用 MultiFieldQueryParser 可以指定多个搜索字段。

    Query query = MultiFieldQueryParser.Parse("name*", new string[] { FieldName, FieldValue }, analyzer);

    IndexReader reader = IndexReader.Open(directory);
    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);

    3. 多条件搜索

    除了使用 QueryParser.Parse 分解复杂的搜索语法外,还可以通过组合多个 Query 来达到目的。

    Query query1 = new TermQuery(new Term(FieldValue, "name1")); // 词语搜索
    Query query2 = new WildcardQuery(new Term(FieldName, "name*")); // 通配符 
    //Query query3 = new PrefixQuery(new Term(FieldName, "name1")); // 字段搜索 Field:Keyword,自动在结尾添加 *
    //Query query4 = new RangeQuery(new Term(FieldNumber, NumberTools.LongToString(11L)), new Term(FieldNumber, NumberTools.LongToString(13L)), true); // 范围搜索
    //Query query5 = new FilteredQuery(query, filter); // 带过滤条件的搜索
          
    BooleanQuery query = new BooleanQuery();
    query.Add(query1, BooleanClause.Occur.MUST);
    query.Add(query2, BooleanClause.Occur.MUST);

    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);

    4. 设置权重

    可以给 Document 和 Field 增加权重(Boost),使其在搜索结果排名更加靠前。缺省情况下,搜索结果以 Document.Score 作为排序依据,该数值越大排名越靠前。Boost 缺省值为 1。

    Score = Score * Boost

    通过上面的公式,我们就可以设置不同的权重来影响排名。

    如下面的例子中根据 VIP 级别设定不同的权重。
    Document document = new Document();
    switch (vip)
    {
      case VIP.Gold: document.SetBoost(2F); break;
      case VIP.Argentine: document.SetBoost(1.5F); break;
    }

    只要 Boost 足够大,那么就可以让某个命中结果永远排第一位,这就是百度等网站的"收费排名"业务。明显有失公平,鄙视一把。  

    5. 排序

    通过 SortField 的构造参数,我们可以设置排序字段,排序条件,以及倒排。

    Sort sort = new Sort(new SortField(FieldName, SortField.DOC, false));

    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query, sort);

    排序对搜索速度影响还是很大的,尽可能不要使用多个排序条件。

    6. 过滤

    使用 Filter 对搜索结果进行过滤,可以获得更小范围内更精确的结果。

    举个例子,我们搜索上架时间在 2005-10-1 到 2005-10-30 之间的商品。
    对于日期时间,我们需要转换一下才能添加到索引库,同时还必须是索引字段。
    // index
    document.Add(FieldDate, DateField.DateToString(date), Field.Store.YES, Field.Index.UN_TOKENIZED);

    //...

    // search
    Filter filter = new DateFilter(FieldDate, DateTime.Parse("2005-10-1"), DateTime.Parse("2005-10-30"));
    Hits hits = searcher.Search(query, filter);

    除了日期时间,还可以使用整数。比如搜索价格在 100 ~ 200 之间的商品。
    Lucene.Net NumberTools 对于数字进行了补位处理,如果需要使用浮点数可以自己参考源码进行。
    // index
    document.Add(new Field(FieldNumber, NumberTools.LongToString((long)price), Field.Store.YES, Field.Index.UN_TOKENIZED));

    //...

    // search
    Filter filter = new RangeFilter(FieldNumber, NumberTools.LongToString(100L), NumberTools.LongToString(200L), true, true);
    Hits hits = searcher.Search(query, filter);

    使用 Query 作为过滤条件。
    QueryFilter filter = new QueryFilter(QueryParser.Parse("name2", FieldValue, analyzer));

    我们还可以使用 FilteredQuery 进行多条件过滤。

    Filter filter = new DateFilter(FieldDate, DateTime.Parse("2005-10-10"), DateTime.Parse("2005-10-15"));
    Filter filter2 = new RangeFilter(FieldNumber, NumberTools.LongToString(11L), NumberTools.LongToString(13L), true, true);

    Query query = QueryParser.Parse("name*", FieldName, analyzer);
    query = new FilteredQuery(query, filter);
    query = new FilteredQuery(query, filter2);

    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);
    7. 分布搜索

    我们可以使用 MultiReader 或 MultiSearcher 搜索多个索引库。

    MultiReader reader = new MultiReader(new IndexReader[] { IndexReader.Open(@"c:\index"), IndexReader.Open(@"\\server\index") });
    IndexSearcher searcher = new IndexSearcher(reader);
    Hits hits = searcher.Search(query);



    IndexSearcher searcher1 = new IndexSearcher(reader1);
    IndexSearcher searcher2 = new IndexSearcher(reader2);
    MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1, searcher2 });
    Hits hits = searcher.Search(query);

    还可以使用 ParallelMultiSearcher 进行多线程并行搜索。

    8. 合并索引库

    将 directory1 合并到 directory2 中。
    Directory directory1 = FSDirectory.GetDirectory("index1", false);
    Directory directory2 = FSDirectory.GetDirectory("index2", false);

    IndexWriter writer = new IndexWriter(directory2, analyzer, false);
    writer.AddIndexes(new Directory[] { directory });
    Console.WriteLine(writer.DocCount());
    writer.Close();

    9. 显示搜索语法字符串

    我们组合了很多种搜索条件,或许想看看与其对等的搜索语法串是什么样的。
    BooleanQuery query = new BooleanQuery();
    query.Add(query1, true, false);
    query.Add(query2, true, false);
    //...

    Console.WriteLine("Syntax: {0}", query.ToString());

    输出:
    Syntax: +(name:name* value:name*) +number:[0000000000000000b TO 0000000000000000d]

    呵呵,就这么简单。

    10. 操作索引库

    删除 (软删除,仅添加了删除标记。调用 IndexWriter.Optimize() 后真正删除。)
    IndexReader reader = IndexReader.Open(directory);

    // 删除指定序号(DocId)的 Document。
    reader.Delete(123);

    // 删除包含指定 Term 的 Document。
    reader.Delete(new Term(FieldValue, "Hello"));

    // 恢复软删除。
    reader.UndeleteAll();

    reader.Close();

    增量更新 (只需将 create 参数设为 false,即可往现有索引库添加新数据。)
    Directory directory = FSDirectory.GetDirectory("index", false);
    IndexWriter writer = new IndexWriter(directory, analyzer, false);
    writer.AddDocument(doc1);
    writer.AddDocument(doc2);
    writer.Optimize();
    writer.Close();

    11. 优化

    批量向 FSDirectory 增加索引时,增大合并因子(mergeFactor )和最小文档合并数(minMergeDocs)有助于提高性能,减少索引时间。

    IndexWriter writer = new IndexWriter(directory, analyzer, true);

    writer.maxFieldLength = 1000; // 字段最大长度
    writer.mergeFactor = 1000;
    writer.minMergeDocs = 1000;

    for (int i = 0; i < 10000; i++)
    {
      // Add Documentes...
    }

    writer.Optimize();
    writer.Close();

    相关参数说明 


    转自《深入 Lucene 索引机制》

    利用 Lucene,在创建索引的工程中你可以充分利用机器的硬件资源来提高索引的效率。当你需要索引大量的文件时,你会注意到索引过程的瓶颈是在往磁盘上写索引文件的过程中。为了解决这个问题, Lucene 在内存中持有一块缓冲区。但我们如何控制 Lucene 的缓冲区呢?幸运的是,Lucene 的类 IndexWriter 提供了三个参数用来调整缓冲区的大小以及往磁盘上写索引文件的频率。

    1.合并因子 (mergeFactor)

    这个参数决定了在 Lucene 的一个索引块中可以存放多少文档以及把磁盘上的索引块合并成一个大的索引块的频率。比如,如果合并因子的值是 10,那么当内存中的文档数达到 10 的时候所有的文档都必须写到磁盘上的一个新的索引块中。并且,如果磁盘上的索引块的隔数达到 10 的话,这 10 个索引块会被合并成一个新的索引块。这个参数的默认值是 10,如果需要索引的文档数非常多的话这个值将是非常不合适的。对批处理的索引来讲,为这个参数赋一个比较大的值会得到比较好的索引效果。

    2.最小合并文档数 (minMergeDocs)

    这个参数也会影响索引的性能。它决定了内存中的文档数至少达到多少才能将它们写回磁盘。这个参数的默认值是10,如果你有足够的内存,那么将这个值尽量设的比较大一些将会显著的提高索引性能。

    3.最大合并文档数 (maxMergeDocs)

    这个参数决定了一个索引块中的最大的文档数。它的默认值是 Integer.MAX_VALUE,将这个参数设置为比较大的值可以提高索引效率和检索速度,由于该参数的默认值是整型的最大值,所以我们一般不需要改动这个参数。
    posted @ 2008-05-27 11:11 隨風.NET 阅读(77) | 评论 (0)编辑

    2008年5月26日

    1 联合两个索引查询,已解决:
    IndexSearcher[] searchers = new IndexSearcher[2]; 
      
    searchers[0] = new IndexSearcher(m_indexpath);
    searchers[1] = new IndexSearcher(m_outindexpath);

    MultiSearcher multiSearcher = new MultiSearcher(searchers);

    2,还有个进行多条件搜索 and 与 or 的操作————
    用 MultiFieldQueryParser
    建议重新封装
    MultiFieldQueryParser.Parser(p[],d[],f[],analyer)  成or 与 and操作合一
    或者 
            BooleanQuery thisQuery = new BooleanQuery();
            thisQuery.Add(query1,true,false);
            thisQuery.Add(query2, false, false);

    posted @ 2008-05-26 17:08 隨風.NET 阅读(72) | 评论 (0)编辑

    导航

    公告

    希望自己能静心写点blog,很多内容来自与互联网,如果没有添加来源,可能是忘记了,还请谅解
    <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    统计

    与我联系

    搜索

     

    常用链接

    留言簿

    我管理的小组

    我参与的团队

    随笔分类(5)

    随笔档案(29)

    links

    最新随笔

    积分与排名

    最新评论

    阅读排行榜

    评论排行榜