各位用户为了找寻关于详细介绍基于MySQL的搜索引擎MySQL-Fullltext的资料费劲了很多周折。这里教程网为您整理了关于详细介绍基于MySQL的搜索引擎MySQL-Fullltext的相关资料,仅供查阅,以下为您介绍关于详细介绍基于MySQL的搜索引擎MySQL-Fullltext的详细内容
本文涵盖了一个简单的C实现的搜索引擎的搭建始末。
我通常使用SQL Server和C #,但我教C/C++的朋友要远离微软。在过去,MySQL不是我想要的数据库,因为标准安装版不支持事务,但它变得越来越成熟。我使用64位InnoDB引擎的MySQL 5.6,使用Unicode(utf8)编码,这是我新数据库的默认设置。
Freetext是InnoDB的新特征,它在MySQL5.6版中被首次推出。
与C相比我通常更喜欢C++,即使在小项目中:不用知道所有的函数名,而且有一些内置的常用操作和漂亮的IntelliSense支持。在C++中,还有有STL及集合和字符串助手。
C++的Mysql接口比较弱,而C的接口很成熟,所以我决定使用C接口。
C的dll文件是和WCF一起发布的,以便完成AJAX请求,在Visual Studio Ultimate 2012中我使用C#的"WCF Service Application"模板,我搜索了使用C++搭建WebService的方法,但只找到一些使用C++处理WebServices调用的例子。
用户界面是一个使用Jquery和Jquery-UI自动提示的HTML界面,页面被增加到"WCF服务应用",项目被命名为VisionWeb
网页看起来是这样的:
我在.NET框架4.0,64位系统上配置这个项目,如果你使用32位的Mysql服务器,你必需随之做些更改。记得设置UNICODE选项为默认值。
配置MySQL
你有可能会从VisionSmall中打开这个VisionDAL项目, 假定你必须修改连接MySQL的C程序接口. 在这儿,我介绍了如何在新项目中安装MySQL接口: 检查那些设置是否符合你的要求,尤其是mysql.lib文件和VisionDAL.dll的路径.
在Visual Studio中,添加一个VisionDAL工程, 通过这个流程"Other Languages/Visual C++/Empty Project". 在这之中, 你只需要改变"应用类型" 为DLL. 把VisionDAL.cpp改名为VisionDAL.c, 这就清楚的告诉Visual Studio把编译器从C++改为C. 给这个工程添加一个头文件命名为VisionDAL.h.
在窗口中, 右击VisionDAL工程并选择属性. 然后在"配置属性"/Linker/Input, 选择 "Additional Dependencies" 并且添加libmysql.lib 到这个路径, 不要忘记了分隔符 ";".
在 "配置属性"/Linker/General这个菜单下, 选择"添加库目录" ,对我来说就是添加 C:Program FilesMySQLMySQL Server 5.6lib>这个目录. 现在我们已经连接到C接口, 但是在libmysql.lib中调用执行的DLL必须是系统的可执行路径: 从控制面板, 选择系统, 点击 "高级系统设置", "点出环境变量" 在 "系统变量"下面,选择路径, 并添加这个 libmysql.lib 的路径 (DLL和这个lib文件在相同的文件夹里): C:Program FilesMySQLMySQL Server 5.6lib.
我们也需要把这个VisionDal.dll放到我们的path路径里, IIS 并不能从这个网站的bin目录中取到DLL文件. 添加 <项目路径>/x64/debug 到路径变量path里. 重启后生效. 当网站得到一个request请求时将会加载VisionDAL.dll; 如果你现在重建项目, 你会得到一个VisionDAL.dll的写入错误: 为了解决它, 重启该网站或是用unlocker之类的解锁.
如果需要指定VisonDAL的包含属性. 在 "配置属性"/"C/C++" 菜单下添加MYSQL的头文件路径, 例如像这样: C:Program FilesMySQLMySQL Server 5.6include.
下面我们在“C/C++”/"预编译头"菜单栏中,从“预编译头”切换到“不使用预编译头”,设置Preproccessor定义防止使用strcpy和fopen时产生的错误消息:在"C/C++"/预编译器/"预编译器定义 "中设定SE_STANDARD_FILE_FUNCTIONS和_CRT_SECURE_NO_WARNINGS。
当你现在连接,mysqllib引用的问题并没有解决,因为它们是64位处理器。通过在VisionDal中打开工程属性,选择“配置管理”,然后设置为x64平台。
现在我们来创建名为 Vision 的样本数据库
打开SQL Development 中的 MySql 工作台,打开你的实例。将会出现一个新窗口 "SQL File 1" 。 双击VisionDAL项目中的 Sql.txt 文件。复制所有内容到剪贴板,粘贴到工作台中的"SQL File 1"窗口。 点击螺栓图标(左边第三个图标),创建样本数据库。 接下来我们需要用来数据库登录的通用信息。
我们有一个关于此的配置文件: <installation director>VisionSmallx64DebugVisionConfiguration.txt, 看起来像这样:
代码如下: Host: localhost User: root Password: frob4frob Database: vision Port: 3306
修改这些数值以匹配你的SQL-Configuration。
Vision 数据库
数据库中只有一张表
? 1 2 3 4 5 6 7 8CREATE
TABLE
'document'
(
'DocumentID'
int
(11)
NOT
NULL
AUTO_INCREMENT,
'Title'
varchar
(255)
DEFAULT
NULL
,
'Text'
text,
PRIMARY
KEY
(
'DocumentID'
),
FULLTEXT
KEY
'ft'
(
'Title'
,
'Text'
),
FULLTEXT
KEY
'ftTitle'
(
'Title'
)
) ENGINE=InnoDB AUTO_INCREMENT=5
DEFAULT
CHARSET=utf8;
搜索的时候我们使用名为'ft'的全文索引,查找自动完成单词的时候我们使用名为'ftTitle'的全文索引。
如果你拥有一个很多字段的全文索引,你可以在Microsoft SQL Server中选择,查询的时候,哪个字段被包含进搜索。在MySQL中,通常全文索引的所有字段都被搜索,所以我们必须指定额外的全文索引'ftTitle'。
通过C接口进行MySQL查询 首先呢,为了执行查询我们需要连接到数据库并取得一个MYSQL的指针:
? 1 2 3 4 5 6 7 8 9 10 11 12 13
MYSQL *
Connect
(){
MYSQL *conn; //
Connection
// 连接到MySQL
conn = mysql_init(
NULL
);
if(mysql_real_connect(
conn, Configuration.Host, Configuration.
User
, Configuration.
Password
,
Configuration.
Database
, Configuration.Port,
NULL
, 0) ==
NULL
) {
fprintf(stderr,
"sorry, no database connection ...n"
);
return
NULL
;
}
return
conn;
}
在启动的时候我们把VisionConfiguration.txt文件里的变量赋值到全局变量, 这个文件应该和我们的程序在同一目录. 这是一个例行操作.获取当前运行程序目录是通过Win32 API的GetModuleFileName函数,如下:
? 1 2 3 4 5 6 7 8
TCHAR *GetExecutablePath(){
TCHAR *pBuf = (TCHAR *)malloc(512);
int
bytes = GetModuleFileName(
NULL
, pBuf, 255);
if(bytes == 0)
return
NULL
;
else
return
pBuf;
}
这里只有一个程序我们想要说明:GetDocuments. 在头文件定义:
? 1 2#define FORMAT_TEXT 0
#define FORMAT_JSON 1
__declspec(dllexport) TCHAR* __cdecl GetDocuments(TCHAR *search, int format, int forAutocomplete); 在资源文件中定义: __declspec(dllexport) TCHAR* GetDocuments(TCHAR *search, int format, int forAutocomplete)
__declspec(dllexport)的声明和定义实现是通过添加到VisionDAL.lib文件并通过VisionDAL.dll文件输出.__cdecl定义如何调用这个过程, 这里我们使用C风格的调用约定.当UNICODE定义被设置时,TCHAR和WCHAR是一样的,否则TCHAR就是一个简单的char, 假定我们这里的UNICODE 已经设置好了.
注意这里有一些不同的 Unicode格式: 在C语言里我们使用两个字节来表示一个char值 在MYSQL和.NET 框架的UTF-8格式, 它意味着一个字节对应一个字符并且仅在超过一个字节被使用时 在终端程序中通过用一个字符对应一个字符并且当值大于127时使用Codepage 850.参数格式是 FORMAT_TEXT 和 FORMAT_JSON,来保证输出在text和 JSON之间.
如果forAutocomplete是true,那么只有标题被搜索并返回.
VisionDALClientConsole
VisionDALClientConsole是一个很小的Windows Console应用程序。测试我们的GetDocuments程序将会涉及到VisionDAL工程集合,它将文件从VisionDAL输出到 VisionSmallx64Debug 。
VisionDALClientConsole 发出搜索字串请求,包括通配符“*”,它将会搜索title列和text列,并通过调用GetDocuments将字符输出。
一个简单的例子:
main 入口:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30int
_tmain(
int
argc,
TCHAR
* argv[])
{
char
c;
TCHAR
*result;
TCHAR
*search = (
TCHAR
*)
malloc
(1000*2);
char
*searchA = (
char
*)
malloc
(1000);
int
retval = 1;
char
buffer[32000];
buffer[0]=0;
printf
(
"Search for: "
);
/* wscanf doesn't get umlauts */
if
(
scanf
(
"%[^n]"
, searchA) <= 0){
printf
(
"Could not read input - retrieving all Documents n"
);
*search=0;
}
else
{
MultiByteToWideChar(850,0,searchA, -1,search, 999);
}
result=GetDocuments(search, FORMAT_TEXT, 0);
if
(result == NULL){
retval = 0;
}
else
{
WideCharToMultiByte(850,0,result, -1,buffer, 32000,NULL,NULL);
printf
(
"%s"
, buffer);
}
fflush
(stdin);
printf
(
"Press RETURN Key to Exitn"
);
getchar
();
return
retval;
}
在Microsoft C V.12中按照惯例可以处理Unicode-16字串。在函数字串开始加上w或是用wcs替换str,如:wscanf,wprintf以及wcslen替换的是strlen。用wscanf不能正确的处理宽窄字符转化。我用MultiByteToWideChar,codepage用850来转化宽字符和用WideCharToMultiByte转化为一般字符。
查询MySQL数据库
上面我演示了如何连接数据库以及获得一个叫做conn的连接点。
接下来我们建立SQL查询:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21mysql_query(conn,
"SET NAMES 'utf8'"
);
if
(forAutocomplete){
if
(search == NULL || wcslen(search) ==0){
WideCharToMultiByte(CP_UTF8,0,
L
"SELECT Title from Document LIMIT 20"
,-1,sql,1000,NULL,NULL);
}
else
{
wsprintf(lbuffer, L"SELECT Title, match(Title) against(
'%ls'
IN
BOOLEAN
MODE) as Score from Document where match(Title) against(
'%ls'
IN
BOOLEAN
MODE) > 0.001 order by Score Desc LIMIT 20",
search, search);
WideCharToMultiByte(CP_UTF8,0,lbuffer,-1,sql,1000,NULL,NULL);
}
}
else
if
(search == NULL || wcslen(search) ==0){
WideCharToMultiByte(CP_UTF8,0,L
"SELECT DocumentID, Title, Text from Document"
,-1,sql,1000,NULL,NULL);
}
else
{
wsprintf(lbuffer, L"SELECT DocumentID, Title, Text, match(Title, Text)
against(
'%ls'
IN
BOOLEAN
MODE) as Score from Document where match(Title, Text)
against(
'%ls'
IN
BOOLEAN
MODE) > 0.001 order by Score Desc",
search, search);
WideCharToMultiByte(CP_UTF8,0,lbuffer,-1,sql,1000,NULL,NULL);
}
查询match(Title, Text) against('%ls' IN BOOLEAN MODE)在列Title和Text中查询要搜索的字符串,并返回一个反馈查询匹配情况的值。只有分数大于0.001的文档将显示,输出结果按评分排序。
IN BOOLEAN MODE时多个单词的搜索分别进行。
在搜索字符串中,你可以使用“*”作为通配符,它匹配0到n个字符。例如“as*”会匹配ASP。搜索不区分大小写。在SQL server中有些例外,“as**”不匹配任何内容,“*SP”也不匹配,你可以在字符串的开头匹配通配符。
获得数据
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
if
(mysql_query(conn, sql)) {
fprintf
(stderr,
"%sn"
, mysql_error(conn));
fprintf
(stderr,
"%sn"
, sql);
return
NULL;
}
// Process results
result = mysql_store_result(conn);
...
while
((row = mysql_fetch_row(result)) != NULL) {
if
(format == FORMAT_TEXT){
MultiByteToWideChar(CP_UTF8,0,row[0], -1,buffer, 255);
wsprintf(resultBufferp,L
"%st"
, buffer);
resultBufferp+=wcslen(buffer)+1;
MultiByteToWideChar(CP_UTF8,0,row[1], -1,buffer, 255);
wsprintf(resultBufferp,L
"%st"
, buffer);
resultBufferp+=wcslen(buffer)+1;
MultiByteToWideChar(CP_UTF8,0,row[2], -1,buffer, 32000);
wsprintf(resultBufferp,L
"%sn"
, buffer);
resultBufferp+=wcslen(buffer)+1;
}
else
if
(format == FORMAT_JSON){
if
(!forAutocomplete){
MultiByteToWideChar(CP_UTF8,0,row[0], -1,buffer, 255);
wsprintf(resultBufferp,L
"{"DocumentID": %s, "
, buffer);
resultBufferp+=wcslen(buffer)+wcslen(L
"{"DocumentID": , "
);
MultiByteToWideChar(CP_UTF8,0,row[1], -1,buffer, 255);
wsprintf(resultBufferp,L
""Title": "%s", "
, buffer);
resultBufferp+=wcslen(buffer)+wcslen(L
""Title": "", "
);
MultiByteToWideChar(CP_UTF8,0,row[2], -1,buffer, 32000);
wsprintf(resultBufferp,L
""Text": "%s"},"
, buffer);
resultBufferp+=wcslen(buffer)+wcslen(L
""Text": ""},"
);
}
else
{
MultiByteToWideChar(CP_UTF8,0,row[0], -1,buffer, 255);
wsprintf(resultBufferp,L
""%s","
, buffer);
resultBufferp+=wcslen(buffer)+wcslen(L
""","
);
}
}
}
mysql_query 将查询发送到服务器。mysql_store_result将结果准备为一个集合,你可用mysql_fetch_row(result)进行迭代。无论列具有什么数据类型,每行都是一个字符串数组。我更喜欢ADO.NET中的具有类型的列。在.NET中,我们可能使用StringBuilder来聚集结果字符串,这里我们通过malloc和增长resultBufferp指针来定位char[]。我们使用MultiByteToWideChar来转换到WCHAR。 JSON 格式
我决定不采用XML格式,而使用轻量级的 JSON-格式,以此来从Web页面通过AJAX与Webservice通讯。
JSON-输出看起来像这样
? 1 2 3 4 5 6 7 8 9 10[{
"DocumentID"
: 1,
"Title"
:
"ASP MVC 4"
,
"Text"
:
"Was für Profis"
},{
"DocumentID"
: 2,
"Title"
:
"JQuery"
,
"Text"
:
"Hat Ajax Support"
},{
"DocumentID"
: 3,
"Title"
:
"
WebServices"
,
"Text"
:
"Visual C++ kanns nicht"
},{
"DocumentID"
: 4,
"Title"
:
"Boost"
,
"Text"
:
"Muss Extra installiert werden"
}]
在参数自动完成为真的时候,JSON-看起来像这样:
?
1
[
"ASP MVC 4"
,
"JQuery"
,
"WebServices"
,
"Boost"
]
"[]" 符号表明了一个数组的开始与结束, "{}" 标明了一个对象的开始与结束。在一个对象中,":"前面的部分是属性名称,在它后面的部分是属性值。与之类似的,在你用JavaScript编码的时候也差不多一样。通过JavaScript-命令JSON.parse,你得到一个完整的对象,这个对象的属性可以通过通常的"." 符号访问。
为 GetDocuments 方法搭建 Webservice
我使用"Visual C#/WCF/WCF Service Application"模板创建了 VisionWeb项目,需要添加必要的System.ServiceModel引用。
下一步我们使用 NuGet 来添加必要的 JavaScript 库。选择 "Tools/Library Packet Manager/Package Manager Console" 并执行如下命令:
? 1 2Install-Package jQuery
Install-Package jQuery.UI.Combined
下一步我们在 “ App-Code/IVisionService.cs” 文件中定义 service contract :
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14namespace
VisionServices
{
[ServiceContract(SessionMode = SessionMode.Allowed)]
public
interface IVisionService
{
[OperationContract]
[WebInvoke(
Method =
"POST"
,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string GetDocuments(string search,
int
format,
int
forautocomplete);
}
}
WebInvoke 属性是保证 service 能够被Ajax调用。我选择POST作为在HTTP请求中传递参数的方式。这个可选择的 GET 方式, 会加密并且暴露在URL中的参数。 我们指定以JSON格式发送请求和响应。当传递一个或多个参数时必须使用
BodyStyle = WebMessageBodyStyle.WrappedRequest。 你可以使用 WebMessageBodyStyle.Bareif ,这样你会得到零或者一个参数。
Webservice的实现
我们将实现定义在 "App-Code/IVisionService.cs"中:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16namespace
VisionServices
{
public
class
PInvoke
{
[DllImport(
"VisionDAL.dll"
, CharSet = CharSet.Unicode)]
public
static
extern
string GetDocuments(string search,
int
format,
int
forAutocomplete);
}
public
class
VisionService : IVisionService
{
public
string GetDocuments(string search,
int
format,
int
forautocomplete)
{
string result = PInvoke.GetDocuments(search, format, forautocomplete).ToString();
return
result;
}
}
}
VisionService.svc的实现
? 1
<%@ ServiceHost Language=
"C#"
Debug=
"true"
Service=
"VisionServices.VisionService"
CodeBehind=
"App_CodeVisionService.cs"
%>
这里定义了调用"http://<your webserver>:<your port>VisionService.svc"时的服务端点 ,调用GetDocuments函数的URL地址是 "http://<your webserver>:<your port>VisionService.svc/GetDocuments"。
Web.config 文件
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35<?
xml
version
=
"1.0"
?>
<
configuration
>
<
appSettings
/>
<
system.web
>
<
httpRuntime
/>
<
compilation
debug
=
"true"
/>
</
system.web
>
<
system.serviceModel
>
<
services
>
<
service
name
=
"VisionServices.VisionService"
>
<
endpoint
address
=
""
binding
=
"webHttpBinding"
contract
=
"VisionServices.IVisionService"
behaviorConfiguration
=
"webHttpEndpoint"
/>
<
endpoint
address
=
"mex"
binding
=
"mexHttpBinding"
contract
=
"IMetadataExchange"
/>
</
service
>
</
services
>
<
behaviors
>
<
endpointBehaviors
>
<
behavior
name
=
"webHttpEndpoint"
>
<
webHttp
helpEnabled
=
"true"
/>
</
behavior
>
</
endpointBehaviors
>
<
serviceBehaviors
>
<
behavior
>
<
serviceMetadata
httpGetEnabled
=
"true"
httpsGetEnabled
=
"true"
/>
<
serviceDebug
includeExceptionDetailInFaults
=
"true"
/>
</
behavior
>
</
serviceBehaviors
>
</
behaviors
>
<
serviceHostingEnvironment
aspNetCompatibilityEnabled
=
"false"
multipleSiteBindingsEnabled
=
"true"
/>
</
system.serviceModel
>
<
system.webServer
>
<
modules
runAllManagedModulesForAllRequests
=
"true"
/>
<
directoryBrowse
enabled
=
"true"
/>
</
system.webServer
>
</
configuration
>
这是允许Ajax请求的配置。 你可以使用很多选项来配置WCF。你可以到Safari上查看更多类似于[2]的文档。
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>配置了一个提供元数据交换的端点,通过元数据你可以自动生成代码来获得WebService代理,比如使用svcutil。选择"Programs/Microsoft Visual Studio 2012/Visual Studio Tools/Developer Command Prompt for VS2012". 输入svcutil http://localhost:8001/VisionService.svc.一个名为VisionService.cs 的文件就生成了, 在其他情况下也会生成一个包含了Webservice配置信息的文件。
托管网站
启动“设置/控制面板/管理工具/ Internet信息服务(IIS)管理器”。当没有安装iis的时候,导航到“应用程序池”,找到正在运行.Net Framework 4.0版本应用程序池的名称,或者添加一个新的应用程序池。导航到“网站”节点,右击它,然后选择“添加网站...”,使用Vision作为网站的名称,为这个应用选择一个正在运行的 .Net Framework 4.0版本应用池。使用 <vision installdir>/VisionWeb作为物理路径,设置端口为8001.选择属性上VisionWeb项目,选择“网络”,选中“使用自定义的Web服务器”,输入服务器URL http://localhost:8001。你可以使用其他的选项来托管网站,例如在IIS Express中,但是如果你不想改变Default.html文件,你必须将端口设置为8001。
HTML/JQuery 页面
在VisionWeb中有个名为Default.html的单一HTML页面,它包含了HTML与JavaScript的内容,它被标为起始页。
同样这里是这个页面的样子:
<
html
>
<
head
>
<
title
>Search</
title
>
<
script
src
=
"Scripts/jquery-2.0.2.js"
></
script
>
<
script
src
=
"Scripts/jquery-ui-1.10.3.js"
></
script
>
<
link
href
=
"Content/themes/base/jquery.ui.autocomplete.css"
rel
=
"stylesheet"
/>
<
style
type
=
text
/css>
.ui-menu-item {
background: White;
}
.ui-helper-hidden-accessible { display:none; }
</
style
>
</
head
>
HTML代码说明了这是一个HTML 5的文档类型。接着我们包含进了必须的JavaScript文件。在jQuery-UI中我们只用到了自动完成插件,为此我们还包含了它的CSS文件。
对于自动完成对象,包含了类[__em all="[object HTMLCollection]"__] .ui-menu-item,我们将背景设置为白色,不然的话它的透明背景会使表格的内容穿透出来。
[__em all="[object HTMLCollection]"__].ui-helper-hidden-accessible { display:none; }将一个烦人的帮助信息从自动完成插件移走。
? 1 2 3 4 5 6<
form
>
<
label
for
=
"search"
>Search:</
label
>
<
input
type
=
"text"
id
=
"search"
,
name
=
"search"
/>
<
input
type
=
"button"
id
=
"update"
name
=
"update"
value
=
"Update"
/>
<
div
id
=
"result"
></
div
>
</
form
>
表单中的元素被赋以了id,因此你可以类似$('#result')用jQuery获得它们。你还可以用jQuery代替缩写的$,例如[__em all="[object HTMLCollection]"__] jQuery('#result')。JavaScript的函数调用document.getElementById('result')具有同样的效果,但是jQuery支持所有类型的CSS选择符。
我使用无侵入的JavaScript,也就是说html代码没有混在JavaScript代码中。事件处理器是在function$(document).ready(function ()方法中绑定的,这个方法会在页面加载后执行。
? 1 2 3 4 5 6 7 8 9 10 11 12 13$(document).ready(
function
() {
$(
'#update'
).bind(
'click'
, GetDocuments);
$(
'#search'
).bind(
"keydown"
, GetInput);
$(
"#search"
).autocomplete({
source:
function
(request, callback) {
GetAutocomplete();
callback(Documents);
},
open:
function
(event) {
var
$ul = $(
this
).autocomplete(
"widget"
);
}
});
});
当你点击"update"按钮的时候会执行GetDocuments方法。它会进行一次全文检索然后将结果显示到一个HTML表格中:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39function
GetDocuments(e) {
var
searchstring = $(
'#search'
).val();
if
(searchstring.length > 0) {
if
(searchstring[searchstring.length - 1] !=
"*"
) {
searchstring +=
"*"
;
}
}
$.ajax({
type:
'POST'
,
url:
'http://localhost:8001/VisionService.svc/GetDocuments'
,
dataType:
'json'
,
crossDomain:
true
,
data: JSON.stringify({ search: searchstring, format: 1, forautocomplete: 0 }),
processData:
true
,
contentType:
"application/json ; charset=utf-8"
,
success:
function
(json, textStatus) {
var
result = JSON.parse(json);
var
display;
display =
""
;
display +=
"<table id='mytable' border=2 <thead><th style='text-align:left'
>ID</th><th style='text-align:left' >Title</th><th
style='text-align:left' >Text</th></thead><tbody>"
;
$.each(result,
function
(index, value) {
display +=
"<tr>"
;
display +=
"<td>"
+ value.DocumentID +
"</td>"
;
display +=
"<td>"
+ value.Title +
"</td>"
;
display +=
"<td>"
+ value.Text +
"</td>"
;
display +=
"<tr>"
;
});
display +=
"</tbody></table>"
;
$(
'#result'
).empty()
$(
'#result'
).html(display);
},
error:
function
(xhr, textStatus, errorThrown) {
alert(
'An error occurred! '
+ (errorThrown ? errorThrown : xhr.status) +
" xhr: "
+ xhr +
" textStatus: "
+ textStatus);
}
});
}
我们把查询表单中"search"字段的值付给变量searchstring,然后,当searchstring中不包含"*"通配符的时候,我们在其后面添加通配符"*",jQuery提供了对Ajax的支持,比如$.ajax()方法。
你可以从这儿查看关于这个方法的说明:jQuery.ajax()。
url:制定了我们在WCF应用中配置好的路径。就如我们在WCF应用中设置的一样,我们使用JSON数据格式。在success方法(这个方法会在ajax请求成功后被异步调用)中,我们获取了json变量,也就是GetDocuments方法输出的值。通过简单的调用JSON.parse(json)方法,我们获得了一个完全成熟的JavaScript对象,我们使用这个对象生成Html表格。result>变量是一个JavaScript对象数组。jquery的$.each方法遍历整个数组,当方法执行的时候,使用当前数组元素的索引和处于当前索引位置的元素作为参数。我们通过调用$('#result').html(display)来显示Html代码,从而生成我们的结果DIV。底层数据:我们使用JSON.stringify方法将用来传输的数据转化为JavaScript对象并将其作为参数。当发生错误的时候,在error:后面的代码将会执行。
自动完成是如何工作的
在我们的 JavaScript 代码开头,我们描述了一个全局变量,用来将用于自动完成的单词保存在一个数组中:var Documents = [];。 函数GetAutocomplete填充了Documents数组。 Autocomplete函数:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24function
GetAutocomplete(e) {
var
searchstring = $(
'#search'
).val();
if
(searchstring.length > 0) {
if
(searchstring[searchstring.length - 1] !=
"*"
) {
searchstring +=
"*"
;
}
}
$.ajax({
type:
'POST'
,
url:
'http://localhost:8001/VisionService.svc/GetDocuments'
,
dataType:
'json'
,
data: JSON.stringify({ search: searchstring, format: 1, forautocomplete: 1}),
processData:
true
,
async:
false
,
contentType:
"application/json ; charset=utf-8"
,
success:
function
(json, textStatus) {
Documents = JSON.parse(json);
},
error:
function
(xhr, textStatus, errorThrown) {
alert(
'An error occurred! '
+ (errorThrown ? errorThrown : xhr.status) +
" xhr: "
+ xhr +
" textStatus: "
+ textStatus);
}
});
}
这看起来非常像GetDocuments函数。success 函数只是更新了Documents变量,通过JSON.parse来将Webservice的输出进行转换。注意async: false,这使得调用是异步的。这个自动完成插件会调用GetAutocomplete函数,并立即显示Documents。
在 $(document).ready(function () 中初始化自动完成插件:
? 1 2 3 4 5 6 7 8 9$(
"#search"
).autocomplete({
source:
function
(request, callback) {
GetAutocomplete();
callback(Documents);
},
open:
function
(event) {
var
$ul = $(
this
).autocomplete(
"widget"
);
}
});
你可以在这里找到关于自动完成的信息:自动完成。
在搜索框中处理 [RETURN] 键:
? 1 2 3 4 5 6 7 8 9$(
'#search'
).bind(
"keydown"
, GetInput);
function
GetInput(e) {
if
(e.keyCode == 13) {
e.preventDefault();
GetDocuments(e);
$(
'#search'
).autocomplete(
"close"
);
}
}
e.preventDefault();停止了对当前事件的处理。
调试
你可以在web浏览器中输入 URL http://localhost:8001/VisionService.svc。如果服务激活失败,将会有一条信息提示,例如 VisionDAL.dll 无法加载。你可以用像Fiddler 之类的工具检测其间的http通信。