[C#]多用户系统如何绑定国际域名

mikel阅读(1250)

多用户系统在网络上很常见,比如淘宝网或者携购网上的店铺就是最典型的多用户系统,每个店主都有一个自己二级域名的小店(如:http://shop88888888.xiegoo.com/),看上去大家都是各自独立的,但从技术曾面来看,其实每个店铺使用的都是同一套程序,唯一的差别就是店铺的界面和数据。

相信实现这样的二级域名指向不同店铺的功能,对大部分程序员来说不是件难事,因为shop后面的88888888里隐藏了店铺唯一的id,通过 shop88888888把这个店铺的界面和数据从数据库里筛选出来是很简单的,我在这里也不详细解释。但是我们经常在网上看到很多“多用户商城”或者“ 建站系统”,支持绑定国际域名,比如携购旗下的独立网店系统http://www.shopxg.com/,只要在线注册,在线绑定国际域名,就能访问自己的网店了。笔者曾经参与开发shopxg,把如何实现这样的功能,拿出来与大家分享,当然可能不是最好最有效的方法,但希望能帮到那些正在为解决这个问题发愁的技术朋友。

因为shopxg是用.NET开发的,所以下面我讲到的情况可能不适合其他语言的系统,但原理是相通的,希望能给您一点启示。

第一步:设计数据库的时候,在“店铺shop”这张表里,要设置一个字段,存放国际域名;

第二步:在shopxg的站点上做泛解析,就是让任何指向到shopxg网站所在服务器的国际域名,都会绑定到shopxg上,至于如何做泛解析,您可以到google查下;

第三步:拿前台的ShopLogin.aspx页面举例,当一个客户输入www.yifull.com/ShopLogin.aspxwww.tiaopidan.com/ShopLogin.aspx的 时候,ShopLogin.aspx页面要马上获取到当前输入的域名,比如使用 Request.ServerVariables["SERVER_NAME"].ToString();当然shopxg使用的是URLRewrite 的重写技术来获取当前域名的,这样的方法有很多,您可以自己选择;

第四步:利用当前的域名,到数据库中精确匹配到某个店铺,然后把该店铺的数据取到前台显示;

当然上面的几步都是非常容易实现的,不是什么难题,但实现了一个多用户系统中每个店铺各自绑定国际域名之后,有很多小问题是不容忽视的:

1.每个页面频繁的获取当前域名,然后到数据库匹配,才知道是哪个店铺在请求数据,会导致系统效率低下,因此我们要让客户在第一次访问一个域名的时 候,把获取回来的店铺编号放进本地cookies,当客户继续访问或者下次来访问的时候,直接从cookies里就能知道当前的域名对应的是哪个店铺了;

2.用户登陆问题:一般的网站都是使用cookies来存放我是否已经登陆某网站的信息的,对于多用户系统,如果用户登陆的时候,cookies没 建好,很容易造成登陆一个网站,就相当于登陆该多用户系统上所有网站;假如可以随意登陆别人的网站后台,那后果将不堪设想;有时候甚至会造成我的定单里有 别人的定单的情况,这都是cookies造成.因此我们在程序建cookies的时候,一定要区分域,在判断用户登陆的过程中,也要严格判断输入的域名和 cookies中的域是否对应;

3.客户在绑定国际域名的时候,一定要判断客户的域名已经存在,并且已经指向了正确的ip,不然一经绑定,客户的网站就无法访问了;

//////获取域名指向的IP

public string GetIPByDomain(string url)
  {
   if (url.Trim() == string.Empty)
    return "";
   try
   {
    System.Net.IPHostEntry host = System.Net.Dns.GetHostByName(url);
    return host.AddressList.GetValue(0).ToString();
   }
   catch (Exception e)
   {
    return "fail";
   }
  }

if(this.GetIPByDomain(this.tbDomian.Text)=="fail")
    {
     Response.Write("<script>alert('系统检测到您的域名不存在,绑定之后会导致您的网站无法访问!');history.go(-1);</script>");
     return;
    }
    if(this.GetIPByDomain(this.tbDomian.Text)!="202.91.243.151")
    {
     Response.Write("<script>alert('系统检测到您的域名还没有指向我们的服务器 202.91.243.151,绑定之后会导致您的网站无法访问!');history.go(-1);</script>");
     return;
    }

4.在程序中任何查询的数据库的操作,必须提供店铺的id才能查询,这样才能避免有人发起恶意操作,把其他网店的信息查询出来.

当然,在实现多用户系统绑定国际域名的时候,会碰到很多其他问题,欢迎大家交流.我的E-mail : cxl@xiegoo.com

[Flex]一周内学会Flex视频合集

mikel阅读(774)

感谢志愿者的辛勤翻译,"一周内学会Flex中文视频翻译"系列终于和众多网友见面了,以下是完整目录。

http://www.riavideo.net/ODT/list.html

第一天

  1. Flex,Flash,Flash Player,AIR概述

  2. 了解Flex Builder

  3. Flex Builder工作空间

  4. 了解Flex预编译组件

  5. 了解MXML

  6. 组件的数据绑定

  7. 处理用户事件

  8. 了解事件对象

  9. 使用ActionScript添加事件侦听器

  10. 使用HttpService获取数据

第二天

  1. 在DataGrid中显示数据

  2. 布局容器的使用

  3. 创建自定义的MXML组件

  4. 实现Value Object类

  5. 创建自定义事件

  6. 创建自定义事件类

  7. 自定义项目渲染器

  8. 探索 Flex Bulider 的使用小窍门

第三天

  1. 数据验证

  2. 使用远程对象来传输数据

  3. 格式化数据

  4. 从列表控件中拖放数据

  5. 使用E4X来过滤XML

  6. 部署Flex和AIR应用

第四天

  1. 执行导航容器

  2. 嵌入图像

  3. 嵌入字体

  4. 创建基于约束的布局

  5. 为MXML组件应用样式

  6. 结合Adobe CS3制作组件皮肤

  7. 创建视图状态

  8. 动画:行为和特效

  9. 结合绘图API绘制图形

  10. 编码实现组件皮肤

  11. 扩展组件

第五天

  1. 了解Flash定时器的行为

更多视频请看:http://www.riavideo.net

[SQLServer]SQL Server2005中文全文搜索问题

mikel阅读(719)

在项目中使用了SQL的全文搜索用来搜索中文的企业名称,但效果一直不理想,比如要搜索“北京三一重工有限公司”,使用“三一”就搜索不到。因是第一次使用SQL的全文搜索,起初以为是SQL的中文分词功能弱的问题,就没有细究。

昨天又重新研究了一下,为了安全起见,我把服务器上的数据导入到开发的机器上做的测试,居然发现在测试的机器上表现相当好。看来不是SQL功能上的问题,是设置上的问题。在网上搜了一下,参考了“一起特殊中文全文检索问题的解决” 这篇文章终于发现了原因。原来是缺少noise.chs文件,补上之后工作正常。

也许这是一个常见的问题,但我想补充一下的就是,大部文章上反应的是少这个文件之后任何查询都会返回“查询子句只包含被忽略的词”,但我遇到的是不 是任何查询都返回“查询子句只包含被忽略的词”,而只是查询功能效果不理想,这样我一直没有想到是noise.chs的问题。

[Lucene]利用Lucene打造站内搜索引擎的思路

mikel阅读(701)

1.为什么要用Lucene,而不用直接从数据库里搜索记录?
主要是考虑到几个因素:(1)性能问题,Lucene是基于文件索引的搜索机制,性能要比数据库里检索更快,特别是数据量大的时候两者区别比较明显。数据 库用Select检索时,默认在执行SQL语句时,会对表锁定,直到查询完成;(2)目前很多网站,都已经将页面静态化,这种情况下,直接用生成的文件编 制索引,再利用Lucene来检索,可以不用查询数据库,减轻了数据库的压力;(3)Lucene可以更方便的进行分词,支持多个关键字检查等操作,在实 现上要比SQL方便;(4)直接基于文件系统的检索,不会有SQL注入风险
2.创建索引
基本上有二种思路,适用于不同的情况
(1)如果网站本身就是静态化的,可以直接读取静态Html文件,来创建索引。注意:如果要实现特定标签的搜索(比如要按产品价格,产品编号,产品摘要, 发布时间等精确搜索产品信息),在读取文件内容时,需要利用正则表达式对Html文件进行匹配分析,得到各个标签的值,再创建Field,加入 Document,最后调用IndexWriter的相应方法创建索引
(2)也可以直接从数据库里查询各标签的值,再按(1)的方法,生成Field–>Document–>加入IndexWriter
3.索引的维护
显然,不可能每次查询都全部将索引生成一次,这里的索引维护主要是索引更新和索引删除,也有两种思路:
(1)找个访问比较少的时段,比如每天晚上0点,做一个C/S程序放在服务器上,用定时器或计划任务全部重新生成索引
(2)更合理有效的方式,是当信息发生修改或删除时,索引维护程序能得到通知,仅更新特定信息的索引就可以了。这里建议用消息队列机制,网站上有信息发生 增,删,改时,将唯一标识值,发送到消息队列,然后索引维护程序监听消息队列,一有消息了,马上根据唯一标识,到数据库里取出修改的信息(或读取修改过的 Html文件),更新指定索引即可
4.分词问题
国内有一些公开的分词组件,可以直接利用,当然有一些是商业化的

[Lucene]DotLucene:37行代码实现全文搜索

mikel阅读(711)

DotLucene是一个强有力的开源全文搜索引擎,它是从Apache的Lucene(java)项目移植到.Net(C#)上的。

DotLucene的效率非常高,并且还具有对搜索结果评级、高光、搜索非结构数据以及本地化等特点。它还和Lucene的索引兼容,因此你可以在不同的平台间迁移而不会丢失任何索引数据。

本文介绍了如何通过简洁的代码来使用DotLucene完成全文搜索功能。

本文翻译自CodeProject上 Dan Letecky 的 DotLucene: Full-Text Search for Your Intranet or Website using 37 Lines of Code 一文,文章版权为原作者所有。

译者:Samuel Chen

Image

DotLucene: 优秀的全文搜索引擎

有可能用37行代码写一个全文搜索么? 恩,我正准备使点小技巧用DotLucene来完成这个麻烦的工作. DotLucene 是一个Jakarta Lucene搜索引擎的移植项目,该项目由 George Aroush et al 维护。下面是它的一些特性:

  • 它能被用在 ASP.NET、WinForms 或者 console 应用;
  • 非常高效的性能; 
  • 搜索结果评级; 
  • 搜索结果中查询关键字高光 ;
  • 搜索结构化和非结构化数据;
  • Metadata 搜索 (时间查询、搜索指定域/字段…)
  • 索引大小大约是索引文本的30%;
  • 并且能存储所有编入索引的文档 Can store also full indexed documents
  • 纯.Net托管代码,单个执行文件 (244 kB)
  • 非常友好的许可 (Apache Software License 2.0)
  • 本地化 (支持 巴西语、捷克语、中文、荷兰语、英语、法语、日语、韩语和俄语)
  • 可扩展 (源代码已包含)
注意

    不要过于在意代码行数。我将用不超过37行代码给你演示他的核心功能,但是要做成一个真正实用的应用,你还需要花更多的时间… 

演示项目

这里,我们将做一个简单的项目演示怎么去做到如下几点:

  • 索引在指定目录(包括子目录)中找到的Html文件
  • 用一个ASP.NET应用程序来搜索索引
  • 搜索结果中高亮显示查询的单词

DotLucene还具有更多的潜力。在实际的应用中你大概想这么去做:

  • 当目录中怎就新文档时添加到索引,而不用重新编译整个索引
  • 包含各种文件类型。DotLuncene能够索引任何能转换成纯文本的文件类型
为什么不使用微软索引服务(Microsoft Indexing Server)?

如果你喜欢用索引服务,没问题。然而,使用DotLucene会有更多好处:

  • DotLucene 是一个100%托管代码的单执行文件,不需要任何依赖
  • 它能被使用到一个共享主机。如果事先准备好索引,你可以不需要磁盘的写权限
  • 使用它,你可以从任何源((数据库、网站…)索引任何类型数据(电子邮件、XML、HTML文件…)。那是因为你需要提供纯文本给索引器(Indexer),载入和解析取决于你
  • 允许你选择要包含在索引中的指定属性("字段"),从而你可以使用这些字段来搜索(例如,作者、日期、关键字等)
  • 它是一个开源软件
  • 它易于扩展
第1行:建立索引

下面的代码从存盘存储建立一个新的索引,directory是存储索引的目录路径参数。

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

这个例子中我们总是重新创建索引(In this example we always create the index from scratch),但这不是必须的,你也可以打开一个已有的索引并添加文档进去。你还可以通过删除然后添加它们的新版本来更新现存的文档(译注:这里应该 是指对象的创建)

第2 – 12行:添加文档

我们为每一个HTML文档添加两个字段到索引:

  • "text" 字段,容纳HTML文件的文本内容(去除了标记),文本数据本身并不会存储在索引中
  • "path" 字段,容纳文件路径,它将会被(索引并)完整的存入索引中
public void AddHtmlDocument(string path)
{
Document doc = new Document();
string rawText;
using (StreamReader sr = new StreamReader(path, System.Text.Encoding.Default))
{
rawText = parseHtml(sr.ReadToEnd());
}
doc.Add(Field.UnStored("text", rawText));
doc.Add(Field.Keyword("path", path));
writer.AddDocument(doc);
}
第13 – 14行:优化并保存索引

添加完文档后,你需要关闭索引器。使用优化将会提高搜索性能。

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

第15行:打开索引搜索

在做任何搜索之前,你需要打开索引。directory参数是存储索引的目录路径。

IndexSearcher searcher = new IndexSearcher(directory);
第16 – 27行:搜索

现在,我们解析查询了("text"是默认搜索字段)

Query query = QueryParser.Parse(q, "text", new StandardAnalyzer());
Hits hits = searcher.Search(query);

变量hits是搜索结果文档的集合,我们将通过它来将结果存储到DataTable

DataTable dt = new DataTable();
dt.Columns.Add("path", typeof(string));
dt.Columns.Add("sample", typeof(string));
for (int i = 0; i < hits.Length(); i++)
{
// get the document from index
Document doc = hits.Doc(i);
// get the document filename
// we can't get the text from the index because we didn't store it there
DataRow row = dt.NewRow();
row["path"] = doc.Get("path");
dt.Rows.Add(row);
}
第28 – 37行:高亮Lines 28 – 37: Query Highlighting

我们先创建一个高亮器对象highlighter,并将使用加黑(bold)字体来高亮显示(<B>查询词</B>)。

QueryHighlightExtractor highlighter = new
QueryHighlightExtractor(query, new StandardAnalyzer(), "<B>", "</B>");

通过对结果遍历,我们将载入原文中最相似的部分。

for (int i = 0; i < hits.Length(); i++)
{
// ...
string plainText;
using (StreamReader sr = new StreamReader(doc.Get("filename"),
System.Text.Encoding.Default))
{
plainText = parseHtml(sr.ReadToEnd());
}
row["sample"] = highlighter.GetBestFragments(plainText, 80, 2, "...");
// ...
}
资源

[Lucene]Lucene.Net系列一 ---simple example

mikel阅读(750)

What’s Lucene
Lucene是一个信息检索的函数库(Library),利用它你可以为你的应用加上索引和搜索的功能.

Lucene的使用者不需要深入了解有关全文检索的知识,仅仅学会使用库中的一个类,你就为你的应用实现全文检索的功能.

不过千万别以为Lucene是一个象google那样的搜索引擎,Lucene甚至不是一个应用程序,它仅仅是一个工具,一个Library.你也 可以把它理解为一个将索引,搜索功能封装的很好的一套简单易用的API.利用这套API你可以做很多有关搜索的事情,而且很方便.

What Can Lucene Do

Lucene可以对任何的数据做索引和搜索. Lucene不管数据源是什么格式,只要它能被转化为文字的形式,就可以被Lucene所分析利用.也就是说不管是MS word, Html ,pdf还是其他什么形式的文件只要你可以从中抽取出文字形式的内容就可以被Lucene所用.你就可以用Lucene对它们进行索引以及搜索.

How To Use Lucene — A Simple Example
示例介绍:

为作为输入参数的文件夹下的所有txt类型的文件做索引,做好的索引文件放入index文件夹.

然后在索引的基础上对文件进行全文搜索.

1.       建立索引

IndexWriter writer = new IndexWriter("index"new StandardAnalyzer(), true);
IndexDocs(writer, 
new System.IO.FileInfo(args[0]));               
writer.Optimize();
writer.Close(); 

IndexWriter是对索引进行写操作的一个类,利用它可以创建一个索引对象然后往其中添加文件.需要注意它并不是唯一可以修改索引的类.在索引建好后利用其他类还可以对其进行修改.

构造函数第一个参数是建立的索引所要放的文件夹的名字.第二个参数是一个分析对象,主要用于从文本中抽取那些需要建立索引的内容,把不需要参与建索 引的文本内容去掉.比如去掉一些a the之类的常用词,还有决定是否大小写敏感.不同的选项通过指定不同的分析对象控制.第三个参数用于确定是否覆盖原有索引的.

第二步就是利用这个writer往索引中添加文件.具体后面再说.

第三步进行优化.

第四步关闭writer.

 

下面具体看看第二步:

 

  public static void IndexDirectory(IndexWriter writer, FileInfo file)
         
{
              
if (Directory.Exists(file.FullName))
              
{
                   String[] files 
= Directory.GetFileSystemEntries(file.FullName);
                   
// an IO error could occur
                   if (files != null)
                   
{
                       
for (int i = 0; i < files.Length; i++)
                       
{
                            IndexDirectory(writer, 
new FileInfo(files[i]));  //这里是一个递归
                       }

                   }

              }

              
else if (file.Extension == ".txt")
              
{
                   IndexFile(file, writer);
              }

         }


 

         
private static void IndexFile(FileInfo file, IndexWriter writer)
         
{
              Console.Out.WriteLine(
"adding " + file);
              
try
              
{
                   Document doc 
= new Document();                   
                   doc.Add(Field.Keyword(
"filename", file.FullName));

                   doc.Add(Field.Text(
"contents"new StreamReader(file.FullName)));

                   writer.AddDocument(doc);
              }

              
              
catch (FileNotFoundException fnfe)
              
{
                   
              }

     }


主要就是两个函数一个用于处理文件夹(不是为文件夹建立索引),一个用于真正为文件建立索引.

因此主要集中看一下IndexFile这个方法.首先建立Document对象,然后为Document对象添加一些属性Field.你可以把Document对象看成是虚拟文件,将来将从此获取信息.而Field则看成是描述此虚拟文件的元数据(metadata).

其中Field包括四个类型:

Keywork

该类型的数据将不被分析,而会被索引并保存保存在索引中.
UnIndexed 该类型的数据不会被分析也不会被索引,但是会保存在索引.
UnStored 和UnIndexed刚好相反,被分析被索引,但是不被保存.
Text 和UnStrored类似.如果值的类型为string还会被保存.如果值的类型为Reader就不会被保存和UnStored一样.

 

最后将每一个Document添加到索引当中.

需要注意的是索引不仅可以建立在文件系统上,也可以建立在内存中.

例如

IndexWriter writer = new IndexWriter("index", new StandardAnalyzer(), true);

在第一个参数不是指定文件夹的名字而是使用Directory对象,并使用它的子类RAMDirectory,就可以将索引建立在内存当中.

 

2.       对索引进行搜索

IndexSearcher indexSearcher= new IndexSearcher(indexDir);
Query query 
= QueryParser.Parse(queryString, "contents",new StandardAnalyzer());
Hits hits 
= indexSearcher.Search(query);

第一步利用IndexSearcher打开索引文件用于后面搜索,其中的参数是索引文件的路径.

第二步使用QueryParser将可读性较好的查询语句(比如查询的词lucene ,以及一些高级方式lucene AND .net)转化为Lucene内部使用的查询对象.

第三步执行搜索.并将结果返回到hits集合.需要注意的是Lucene并不是一次将所有的结果放入hits中而是采取一次放一部分的方式.出于空间考虑.

至此,本文演示了如何从一个文件夹下的所有txt文件中查找特定的词。并围绕该个实例介绍了lucene.net的索引的建立以及如何针对索引进行搜索.最后给出源代码供大家学习.

[Lucene]为自己的系统搞个全文搜索

mikel阅读(704)

为自己的系统搞个全文搜索
 
在本文我又提到lucene了,在java业界,提到全文检索,几乎没有什么人不知道它。
用google搜索一下,满世界都是有关资料。具有代表性的就是车东的“基于Java的全
文索引引擎Lucene简介”,我要写的也就只有最简单的三板斧,再加上支持中文的
ChineseAnalyzer以及按照时间排序的搜索结果排序方法。这些都可以在其他地方找
到相关资料,我只是把他们提出来,作为lucence应用中经常遇到的麻烦解决办法。
去年MSN上面有个朋友跟我提到希望用lucene构建个网站的全文检索,我当时就觉得
很简单,直说没问题没问题,不过他提到一个要求就是搜索结果要安装时间排序,
我查阅了些资料,发现lucene并不提供用户自定义排序方式,而只能按照自己相关
性算法排序。后来我在车东的weblucene项目找到了IndexOrderSearcher。解决了结
果排序常规需求。IndexOrderSearcher跟一般IndexSearch使用差不多,仅仅在构建
对象的时候多加一个参数IndexOrderSearcher.ORDER_BY_DOCID_DESC
IndexOrderSearcher indexsearcher =
new IndexOrderSearcher("/home/lucenetest/index",IndexOrderSearcher.ORDER_BY_DOCID_DESC);
新版本的lucene还提供了一个MultiFieldQueryParser,可以同时检索多个字段,以前
QueryParser比较麻烦。

private  static  ChineseAnalyzer  chineseAnalyzer  =  new  ChineseAnalyzer();
public  Hits  search(String  queryText)
{
 if  (queryText  ==  null)
        {
         return  null;
 }
 Query  query;
   try
   {
         query  =  MultiFieldQueryParser.parse(queryText,  new  String[]{"title"},chineseAnalyzer);
        return  indexsearcher.search(query);
   }
   catch(Exception  e)
   {
        return  null;
   }
}
下面是构建索引,定时从数据库取出数据索引,做完记录完成时间,我是把时间写入一个txt文件。
package  com.test.search;
import  org.apache.lucene.analysis.Analyzer;
import  org.apache.lucene.analysis.cn.*;
import  org.apache.lucene.analysis.standard.StandardAnalyzer;
import  org.apache.lucene.document.*;
import  org.apache.lucene.index.*;

import  java.io.*;
import  java.SQL.*;
import  java.util.Date;

import  com.test.db.*;
import  com.test.utility.*;

/**
  *  Title:  SearchIndexer
  *  Description:  全文索引
  *  Copyright:      Copyright  (c)  2001
  *  Company:  test
  *  @author  Sean
  *  @version  1.0
  */
public  class  SearchIndexer 
{
    private  String  indexPath  =  null;
    protected  Analyzer  analyzer  =  new  ChineseAnalyzer();

    public  SearchIndexer(String  s) 
    {
        this.indexPath  =  s;
    }
    /**
      *  索引某日期以前的所有文档
      *  @param  fromdate
      *  @return
      */
    public  final  void  updateIndex(String  fromdate) 
    {
        Connection  conn  =  DbUtil.getCon();
        IndexWriter  indexWriter  =  null;
        try 
        {
             indexWriter  =  getWriter(false);
             //索引发布系统内部文件
                PreparedStatement  pstm  =  conn.prepareStatement(
                        "select  title,body,creationtime  from  document 
                        where  creationtime  >  '"  +  fromdate  +
                        "'  order  by  creationtime");
                ResultSet  rs  =  pstm.executeQuery();
                while  (rs.next()) 
                {
                    String  creationtime  =  rs.getString("creationtime");
                    String  title  =  rs.getString("title");
                    String  body  =  rs.getString("body");

                   
                    if  (title  ==  null  ||  body  ==  null) 
                    {
                        continue;
                    }
                    try 
                    {
                        addDocsToIndex(title,body,  creationtime,indexWriter);
                    }
                    catch  (Exception  ex) 
                    {
                        ex.printStackTrace();
                    }
              }
            indexWriter.optimize();
        }
        catch  (Exception  ex) 
        {
            ex.printStackTrace();
        }
        finally 
        {
            try 
            {
                indexWriter.close();
                conn.close();
            }
            catch  (Exception  e) 
            {
                e.printStackTrace();
            }
        }
    }
    /**
      *  检查索引文件是否存在
      *  @param  s
      *  @return  索引是否存在
      */
    private  boolean  indexExists(String  s) 
    {
        File  file  =  new  File(s  +  File.separator  +  "segments");
        return  file.exists();
    }
    /**
      *  增加一组索引
      *  @param  title
      *  @param  body
      *  @param  creationtime
      *  @param  indexwriter
      *  @return
      */
    private  final  void  addNewsToIndex(String  docid,  String  url,String  title,  String  body,
                                String  ptime,  IndexWriter  indexwriter)  throws IOException 
    {
        if  (indexwriter  ==  null) 
        {
            return;
        }
        else 
        {
            try 
            {
                Document  document  =  new  Document();
                document.add(Field.Text("title",  title));
                document.add(Field.Text("body",  body));
                document.add(new  Field("creationtime",  creationtime,  true,  true,  false));
                indexwriter.addDocument(document);
            }
            catch  (Exception  ex) 
            {
         ex.printStackTrace();
            }
            return;
        }
    }
    /**
      *  取得IndexWriter
      *  @param  flag  是否新建索引
      *  @return  IndexWriter
      */
    private  IndexWriter  getWriter(boolean  flag)  throws  IOException 
    {
        String  s  =  indexPath;
        if  (s  ==  null) 
        {
            throw  new  IOException("索引文件路径设置错误.");
        }
        indexPath  =  s  +  File.separator  +  "search";
        IndexWriter  indexwriter  =  null;
        if  (flag) 
        {
            try 
            {
                indexwriter  =  new  IndexWriter(indexPath,  analyzer,  true);
            }
            catch  (Exception  exception) 
            {
                System.err.println("ERROR:  Failed  to  create  a  new  index  writer.");
                exception.printStackTrace();
            }
        }
        else 
        {
            if  (indexExists(indexPath)) 
            {
                try 
                {
                    indexwriter  =  new  IndexWriter(indexPath,  analyzer,  false);
                }
                catch  (Exception  exception1) 
                {
                    System.err.println("ERROR:  Failed  to  open  an  index  writer.");
                    exception1.printStackTrace();
                }
            }
            else 
            {
                try  {
                    indexwriter  =  new  IndexWriter(indexPath,  analyzer,  true);
                }
                catch  (Exception  exception2) 
                {
                    System.err.println("ERROR:  Failed  to  create  a  new  index  writer.");
                    exception2.printStackTrace();
                }
            }
        }
        return  indexwriter;
    }

    public  static  void  main(String[]  args) 
    {
        String  lastUpdate  =  "/home/lucenetest/lastUpdate.txt";
        SearchIndexer  searchIndexer  =  new  SearchIndexer("/home/lucenetest/index");
        //取出上次更新时间
        String  str  =  Util.readTxtFile(lastUpdate);
        if(str==null  ||  str.length()==0)
        {
            str  =  new  java.util.Date().toString();
        }
        searchIndexer.updateIndex(str);
        //写入当前时间
        Util.writeTxtFile(lastUpdate,new  java.util.Date(),false);
    }
}

写个cmd或者sh在相应操作系统下面定时执行SearchIndexer就可以了

[SQLServer]SQL Server2005全文索引

mikel阅读(733)

Microsoft SQL Server 2005 引入了新的 Transact-SQL 数据定义语言 (DDL) 语句,用来创建、实现和管理全文目录和索引。以下是新的全文搜索 DDL 语句的列表。
Create FULLTEXT CATALOG (Transact-SQL)
使用此语句可以为数据库创建全文目录。
Create FULLTEXT INDEX (Transact-SQL)
使用此语句可以针对数据库某个表的一列或多列创建全文索引。
Alter FULLTEXT CATALOG (Transact-SQL)
使用此语句可以更改全文目录的属性。
Alter FULLTEXT INDEX (Transact-SQL)
使用此语句可以更改全文索引的属性。
Drop FULLTEXT CATALOG (Transact-SQL)
使用此语句可以删除全文目录。
Drop FULLTEXT INDEX (Transact-SQL)
使用此语句可以从指定的表中删除全文索引。

 

———————————————————————————-

而以下是老旧的sql2000的方法:

———————————————————————————-
一个完整的SQL SERVER数据库全文索引的示例。(以pubs数据库为例)

首先,介绍利用系统存储过程创建全文索引的具体步骤:

1) 启动数据库的全文处理功能 (sp_fulltext_database)
2) 建立全文目录 (sp_fulltext_catalog)
3) 在全文目录中注册需要全文索引的表 (sp_fulltext_table)
4) 指出表中需要全文索引的列名 (sp_fulltext_column)
5) 为表创建全文索引 (sp_fulltext_table)
6) 填充全文目录 (sp_fulltext_catalog)


———********示例********————-
以对pubs数据库的title和notes列建立全文索引,之后使用索引查询title列或notes列中包含有datebase 或computer字符串的图书名称:

在这之前,需要安装Microsoft Search服务,启动SQL server全文搜索服务


user pubs –打开数据库
go
–检查数据库pubs是否支持全文索引,如果不支持
–则使用sp_fulltext_database 打开该功能
if(select databaseproperty('pubs','isfulltextenabled'))=0
execute sp_fulltext_database 'enable'

–建立全文目录FT_PUBS
execute sp_fulltext_catalog 'FT_pubs','create'

–为title表建立全文索引数据元
execute sp_fulltext_table 'title','create','FT_pubs','UPKCL_titleidind'

–设置全文索引列名
execute sp_fulltext_column 'title','title','add'
execute sp_fulltext_column 'title','notes','add'

–建立全文索引
–activate,是激活表的全文检索能力,也就是在全文目录中注册该表
execute sp_fulltext_table 'title','activate'

–填充全文索引目录
execute sp_fulltext_catalog 'FT_pubs','start_full'
go

–检查全文目录填充情况
While fulltextcatalogproperty('FT_pubs','populateStatus') <>0
begin

–如果全文目录正处于填充状态,则等待30秒后再检测一次
waitfor delay '0:0:30'
end

–全文目录填充完成后,即可使用全文目录检索

select title
form
where CONTAINS(title,'database')
or CONTAINS(title,'computer')
or CONTAINS(notes,'database')
or CONTAINS(notes,'database')


'————–以下介绍一下全文操作类的系统存储过程
过程名称:sp_fulltext_service
执行权限:serveradmin或系统管理员
作 用:设置全文搜索属性


过程名称:sp_fulltext_catalog
执行权限:db_owner及更高角色成员
作 用:创建和删除一个全文目录,启动或停止一个全文目录的索引操作


过程名称:sp_fulltext_database
执行权限:db_owner角色成员
作 用:初始化全文索引或删除数据库中所有全文目录


过程名称:sp_fulltext_table
执行权限:db_ddladnmin或db_owner角色成员
作 用:将一个表标识为全文索引表或非全文索引表


过程名称:sp_fulltext_column
执行权限:db_ddladnmin角色成员
作 用:指出一个全文索引表中的那些列假如或退出全文索引

[设计]如何设计通用的网站模板

mikel阅读(892)

现在网络上已经到处可以看到使用模板开发出来的网站。使用模板开发网站有很多好处,最主要的就是模板与程序完全脱离,用户可以根据规定好的标签任意开发模 板,导入到模板引擎里就能正常运行。所以美工人员跟程序编写人员彻底的独立了。提高了开发网站的效率,程序的重用性发挥的淋漓尽致。
    智能建站系统、速成网站、自助建站系统、只会打字就能做网站,等等广告字眼我们已经不再陌生了,所有的这些无非都是围绕着模板做文章。也正是因为 这样的系统越来越普及,对于要求不高的企业或者个人用户,拥有一个完全属于自己的网站,用现成的模板要比找网络公司定制省钱的多。性价比要高的多,所以目 前中小型网络公司的生存问题堪忧。
    提供模板做论坛的discuz公司,各位站长应该都很熟悉,但是做企业网站、独立购物网系统,国内做的比较好的几家公司,想必大家可能不太熟悉:ShopEx携购网店系统(ShopXG)HiShop狼烟网络(mynet.cn) 等等,大家有机会可以去他们的官网看看各自的优势。
    下面我们来详细讲解下如何开发网站模板。
    涉及到模板的部分我们可以分成以下几块:自定义标签、模板文件、数据控制项、模板引擎
    1. 自定义标签 自定义标签是模板文件与模板引擎之间交互的基础,也可以说是协议。 目前网络上普遍的标签样式为:{$****} {#*****#},这样的表示方法,主要是为了区分html等脚本标签。 标签的内容区可以设置多种属性。比如len=100 表示数据长度不超过100个字节。 标签变量根据不同的类型,我们可以把名称规定为如下方式:
    {$var_**} 变量标签,表示这个标签的数据来源是某一个字段的值
    {$const_**} 常量标签,表示这个标签是一个常量数据,比如,当前的日期等
    {$temp_small} 小模板数据。(什么叫小模板,我们在后面详细讲解)
    {$page_**} 分页数据。例如首页,上页,下页等翻页的代码部分。等等。
    举例:{$var_news_title len=30} 表示显示新闻的标题,如果新闻标题的字数超过 30个字,那么截取。
    2.模板文件
    模板文件就是由美工人员开发的脚本代码,里面不涉及到任何程序。由于数据经常会涉及到一个循环显示的问题,所以我们把模板文件又分成:大模板、小模板。
    模板文件一般都是普通的html文件,源代码里包含了事先约定好的自定义标签,
    图标说明每个模块的共性:

    图1:新闻列表        图2:产品列表
    大家看上面两个模块,一个是新闻列表,一个是产品列表。无论从数据类型还是展现方式上乍一看截然不同。
    但是大家仔细的看一下,很容易看出来他们其实有很多共同的特点–他们都是有大模板(模块的外框部分)、小模板(模块的数据循环部分)组成。另外,大家可以去找个网站分解下看看。是不是都可以把他们分解成不同的模块,然后每个模块又可以分成大模板、小模板组成。
    我们以上图中新闻列表来给大家讲解下:
    大模板文件就是整个外框部分。基本html如下面所示:

	<div  class=”newslist”>
<h>携购网店 – 不可多得的创业好项目</h>
<ul>代理商加盟携购之后能得到什么?!</ul>
<div>{$temp_small}</div>
</div>

    从上面可以看出,大模板文件里并没有涉及到数据部分,只有一个小模板标签{$temp_small} ,当模板引擎解析到这个标签的时候,将对应的小模板文件解析后,用最终生成的html数据将该标签替换掉。
    接下来,我们来看一下小模板的组成:
    这里特别需要注意下,当模板引擎在解析小模板的时候,是把小模板的数据当作一个循环体,说明白些:比如有10条新闻,那么模板引擎将循环10次小模板数据,将具体的新闻内容分别去替换小模板里的标签,然后组合成一个最终的html.
    小模板的脚本部分:

	<ul  clas=”small_item”>
<li>{$var_news_title  len=100}</li>
<li>{$var_news_add_time}</li>
</ul>

    当然,需要分页的时候,还需要做分页模板,解析引擎会解析分页模板后,将查询到的当前数据替换掉对应的分页变量标签,最后,替换掉大模板中的分页模板标签。
    分页的脚本部分举例:

		<a href="{$var_link_firstpage_link}" id="modulelist_linkup_first">首页</a>
<a href="{$var_link_prevpage_link}" id="modulelist_linkup_prev">上一页</a>
{$var_link_pageteam} <a href="{$var_link_nextpage_link}" id="modulelist_linkup_next">下一页</a>
<a href="{$var_link_lastpage_link}" id="modulelist_linkup_last">末页</a>总数:{$var_link_totalnum} 每页条数:{$var_link_perpagecnt}
总页数:{$var_link_totalpage}当前页码:{$var_link_curpagenum}/{$var_link_totalpage}

    最后从结构上我们再总结下模板的组成关系:

    3.数据控制部分
    该部分是要将哪些数据展示在模板数据项的核心。主要包括以下几部分:
    a. 查询条件 ,从数据库里要查出哪些数据。
    b. 排序类型, 将查询得到的数据,通过何种方式进行排序展示。
    c. 当前页码, 跟每页显示条数配合使用,
    d. 每页显示条数
    e. 是否忽略URL地址里传过来的参数,这个项非常重要,因为像分页和查询,他们都需要从url将参数传过来,而有些定死的数据又不希望受到url参数的影响,所以该项在控制数据显示方面尤为重要。
    f. 接受url的参数列表。等等.
    有了数据控制部分,才能让相同类型的模块展示不同的数据。
    4. 模板引擎
    我们知道模板文件是静态的html脚本页面,它并不具有业务操作能力,单纯的模板没有任何存在的意义。需要模板引擎通过数据控制将获取到的数据按照模板文件规定的样式展示出来,
    模板引擎的好坏,直接影响到整个程序的性能,模板要跟数据库打交道,由于模板文件有非常多的数据冗余,而且,设计不合理的模板,同个页面可能需要多次相同的数据库查询操作,如果模板引擎不能很好的区分出来。那么对数据库的压力也是非常大的。
    如果大家对开发模板网站有兴趣,强烈推荐去用下携购公司开发的VTEditor可视化网站模板开发系统。官方网站:http://www.xiegoo.com/ .是目前唯一真正实现可视化模板编辑的系统。