Developer on Alibaba Coud: Build your first app with APIs, SDKs, and tutorials on the Alibaba Cloud. Read more ＞
Server|web| Program | full-Text Search
Build a WEB Search application using Microsoft SQL Server 2000 Full-text search capabilities Andrew B. Cencinimicrosoft Corporation December 2002 applies To: &NBSP;&NBSP;&NBSP;&N Bsp Microsoft®sql™server 2000 Summary: Learn how to take advantage of the full text search capabilities of SQL Server 2000. This article contains several tips and tricks for achieving maximum throughput and best performance. Introduction to Catalog Introduction to full-text search features configuring Full-text search features full-text query placement and optimization of other performance tips Appendix A: Best choice for full-text search Appendix B: Sample Applications with best choice, results paging, and valid Full-text query logic Appendix C: Introduction to Resources using MICROSOFT®SQ The Full-text search feature of L™server 2000 enables fast, flexible querying of indexes generated on unstructured text data. The popular Full-text search tool is the search engine for the website. To help readers understand the best use of Full-text search capabilities, this article introduces a large number of abstract concepts and provides several tips and tricks for optimizing full-text indexing and querying for maximum throughput and optimal performance. Introduction to Full-text search features the Full-text search feature is introduced in SQL Server 7.0. The core engine for Full-text search is built on Microsoft Search (MSSearch) technology, and is also used in products such as Microsoft Exchange and Microsoft Sharepoint™portal Server. Features that are exposed in SQL Server 7.0 Full-text search provide basic text search capabilities and use earlier versions of MSSearch, while the full text search implementation of SQL Server 2000 contains a set of reliable indexes and query capabilities and is added on top of SQL Server 7.0 Several enhancements. These enhancements include full support for cluster operations through Microsoft Cluster service, the ability to filter and index documents stored in IMAGE columns, improved language support, and improved performance, scalability, and reliability. MSSearch generates, maintains, and queries full-text indexes stored in the file system, not in SQL Server. The logical and physical storage unit used by MSSearch for Full-text indexing is the directory. Full-text catalogs contain one or more Full-text indexes per database-You can create a Full-text index for each table in SQL Server, and the index can contain one or more columns in that table.Each table can only belong to one directory, and each table can only create one index. We'll brief you on the best way to organize your Full-text catalogs and indexes-but first, let's take a quick look at how Full-text search works. Configuring the Full-text Search feature to create a full-text index for text data stored in SQL Server, you should complete the following steps before you prepare. The first step is to enable the Full-text database that contains the text data that you want to generate the index (if you have not already done so). Note: Execute the following statement to discard and recreate all Full-text catalogs that belong to the database for which you want to enable Full-text search. Unless you want to re-create the Full-text catalog, make sure that no Full-text catalogs are created in the specific database that you want to enable. If you are a member of the sysadmin role or the db_owner of this database, you can proceed and issue the following statement: Use Northwind exec sp_fulltext_database ' Enable '
Next, you need to create a Full-text catalog to store Full-text indexes. As mentioned earlier, the data in this directory is stored in the file system (not in SQL Server), so you should choose carefully when considering where to store the Full-text catalog. Unless you specify a different location, the Full-text catalog is stored in a subdirectory of the Ftdata directory (in the Microsoft SQL server\mssql storage location). Here's how to create a Full-text catalog in a non-default location: exec sp_fulltext_catalog ' cat_desc ', ' create ', ' f:\ft '
In this case, the Full-text catalog will be created as a subdirectory of "f:\ft", and if you look at that part of the file system, you will see that it has its own directory. The naming convention for Full-text catalogs used by MSSearch is: Sql+dbid+catalogid
The directory ID starts at 00005 and increments by 1 for each new directory. If possible, it is a good idea to create a Full-text catalog on the physical drive on which it resides. If a process that generates Full-text indexing requires a large amount of I/O operations (specifically, reading data from SQL Server and then writing to the file system), you should avoid making the I/O subsystem a bottleneck. So, how big is the Full-text catalog? In general, the system overhead of a Full-text catalog is about 30% higher than the amount of data stored in SQL Server (full-text indexed), but this rule depends on the distribution of the only word (or primary key) in the data, and the word that you see as a noise word. A noise word (or terminator) is a word that you want to exclude from the Full-text Index and query (because they are not the search term that you are interested in, and the frequency is high, so you will only make the index very large without actual effect). Later, we'll look at considerations for noise word selection and how to optimize noise words to improve query performance. If you have not already done so, create a unique Single-column Non-empty index on each table that you want to generate a Full-text index. This unique index is used to map each row in the table to a uniquely Compressible primary key used internally by the MSSearch. Next, you need to let MSSearch know that you want to create a Full-text index for the table. Issuing the following statement to a table adds the table to the selected Full-text catalog (in this case, it is the "Cat_desc" we created earlier): EXEC sp_fulltext_table ' Categories ', ' create ', ' cat_desc ', ' pk_ Categories '
The next step is to add columns to this Full-text index. You can select a language for each column, and if the column is of type IMAGE, you must specify another column to indicate which document type is stored in each row of the IMAGE column. There are some important but unwritten considerations in the choice of the column language. These considerations relate to how the text is tagged and how the MSSearch indexes the text. The indexed text is provided by a component called a word delimiter (used as a word boundary marker). In English, a word delimiter is usually a space or some form of punctuation, whereas in other languages (such as German), words or characters can be grouped together; Therefore, the selected column language should represent the language to be stored in the row of the column. If you are unsure, the best approach is usually to use a neutral word delimiter (using only spaces and punctuation marks to perform the tag function). Another benefit of choosing a column language is "root-tracing". The root-seeking traceability in full-text query refers to the process of searching for all the changing forms of a word in a particular language. Another consideration for choosing a language relates to how the data is represented. For non-IMAGE column data, you do not need to perform special filtering operations, and text typically requires the word-delimited component to be passed as-is. The word separator is primarily used to process written text. Therefore, if there are any type of markup (such as HTML) in the text, the language accuracy will not be high in the index and search process. In this case, you have two choices-the preferred method is to simply store the text data in the IMAGE column and indicate its document type so that it can be filtered. If you do not select this method, you can consider using a neutral word delimiter and, if possible, add tagged data (such as "BR" in HTML) to the list of noise words. In a column that specifies a neutral language, no language-based root-tracing is possible, but some environments may require you to choose this method. After you know the column options, add a column or two columns to the Full-text index by issuing the following statement: EXEC sp_fulltext_column ' Categories ', ' Description ', ' Add '
You may notice that no language is specified here-in this case, the default Full-text language is used. You can set the default Full-text language for the server through the system stored procedure "sp_configure". After you have added all the columns to the Full-text index, you can perform the fill operation. The number of padding methods is too numerous to be described in detail here. In this case, just start a full population of the table and wait for it to finish: exec sp_fulltext_table ' Categories ', ' start_full '
You may want to use the FullTextCatalogProperty or OBJECTPROPERTY functions to monitor the fill state. To get the directory fill state, you can perform: Select FullTextCatalogProperty (' Cat_desc ', ' populatestatus ')
Typically, if a full population is in progress, the return result is "1". For more information about how to use FullTextCatalogProperty and objectproperty, see SQL Server Books Online. Full-text query query Full-text indexing is slightly different from executing standard relational queries in SQL Server. Because indexes are stored and managed outside of SQL Server, the majority of Full-text query processing is done by MSSearch (therefore, those parts are relational and part of the Full-text query will be handled separately), which can sometimes compromise performance. In essence, when executing a full-text query, the query word is passed to MSSearch, which traverses its internal data structure (the index) and returns the primary key and the rank value to SQL Server. If you perform a CONTAINS or FREETEXT query, you typically do not see primary keys or rank values, but if you perform containstable or freetexttable queries, they are obtained, and these values are typically merged with the base table. The process of merging primary keys with base tables requires a high overhead-later, we'll show you some ingenious ways to minimize or completely avoid this merging. If you have a rudimentary understanding of how a Full-text query returns data by thinking about it, you can speculate that the Contains/freetext query executes only containstable/freetexttable queries and merges with base tables. With this understanding, you should avoid using these types of queries unless the overhead is higher. In Web search applications, using CONTAINSTABLE and freetexttable is much better than using a similar function without a TABLE. Until now, you know that a full-text query is a special way to access data from a MSSearch index stored outside of SQL Server, and that if you blindly merge with a base table, you'll get into trouble. Another important aspect that should be understood is the essential difference between a CONTAINS style query and a FREETEXT style query. CONTAINS queries are used to perform exact matching queries on all the words that are queried. Whether you find only a single word, or find all words that start with "orange," the system returns only the results that contain all the search terms. As a result, CONTAINS queries are fast because they usually return very few results and do not need to perform too much additional processing. The disadvantages of the CONTAINS query include the annoying filtering problem of noise words. Experienced developers and database administrators who used Full-text search in the past, trying to match a packageWhen you have a word or phrase with a single noise word, you have encountered an astonishing error such as "Your query contains only noise words." One way to avoid receiving this error is to filter out the noise word before executing the full-text query. It is not possible to return results to a CONTAINS query that contains noise words because such queries return only the results that exactly match the entire query string. Because noise words are not full-text indexed entries, CONTAINS queries that contain noise words do not return any rows. The FREETEXT query eliminates all the warning descriptions that occur occasionally in a CONTAINS query. When a FREETEXT query is issued, the root query is actually emitted. Therefore, when you search for "root Beer", "root" and "beer" contain all of its forms (root-tracing is related to language; The language is determined by the Full-text column language specified when the index was generated, and must be the same in all the columns of the query), and the system returns all rows that match at least one of these words. The downside of FREETEXT queries is that they typically consume more CPUs than CONTAINS queries-because of the need to include more complex rank calculations to root out and return more results. However, FREETEXT based queries are flexible and very fast and are the best choice commonly used in web-based search applications. Rank and optimize I often encounter users who use Full-text search, they ask me what the rank number means, and how to convert the rank number to a value that a user can understand. On this question, the answer can be long and short, here I will give a brief answer. In simple terms, these rank numbers are not as important as the order in which the results are returned. That is, when you sort the results by rank, you always return the result with the highest degree of association. The rank value itself often changes-full-text search uses the probability rank algorithm, where the correlation of each document returned is directly affected by any or all other documents in the Full-text index. Some people think that one technique that helps increase some row rank is to repeat the frequently used search keywords in the full-text indexed columns of these rows. Although this approach may, to some extent, increase the likelihood that these rows will be returned first due to some keywords, in other cases it may backfire-and there is a risk that the word query performance will be reduced. A better solution is to implement the "best choice" System for search applications (see the following example), which ensures that some documents are returned first. Repeated use of keywords will widen the full-text indexing of these specific keywords and allow MSSearch to waste time finding the correct rows and counting the rows. If you have a large number of full-text indexing data and try to use this method, you may find that some full-text queries are time-consuming. If you can achieve a more granular (and possibly more accurate) "Best choice" system, you will find that it significantly improves query performance. Another problem with multiple duplicate data and for groupsrelational queries and full-text queries are common techniques. Many users who use Full-text search are plagued by this problem, and they encounter this problem whenever they try to apply a filter to the results returned by a full-text query. As mentioned earlier, a Full-text query returns a primary key and a rank for each matching row-to collect any details about the rows, you must merge with its base table. Because any number of results may be returned from an unrestricted Full-text query, merging may require a large amount of system overhead. One effective way to avoid merging is to add only the data that you want to filter in the Full-text index, if possible. In other words, if the user wants to search for the keyword "Ichiro" from the body of all articles in the newspaper and only want to return the article in the sports column in that newspaper, the query usually looks like this:--[Method 1:]--overhead: First Select all, then merge and filter select articles _tbl. Author, Articles_tbl. Body, ARTICLES_TBL. Dateline, Ft_tbl. [Rank] From FREETEXTTABLE (articles, body, ' Ichiro ') as Ft_tblinner JOIN articles as Articles_tblon ft_tbl. [Key] = Articles_tbl. Articleidwhere ARTICLES_TBL. Category = ' Sports '
--[Method 2:]--can be used, but will cause unexpected results and slow, or will return inaccurate results:--perform full-text filtering and extract only primary keys and rank--(process on WEB server completion) SELECT [key], [rank] from CONTAINSTABLE ( Articles, *, ' Formsof (inflectional (' Ichiro ') and ' sports ')
These two queries either unnecessarily consume a large amount of overhead, or have the possibility of returning erroneous results (in the second query, "Sports" is likely to appear in all types of articles). There are other variants of these two technologies, but these are two very simple models. If it works, I usually recommend that you divide the data horizontally. That is, each possible value for the category column is a column (or table), and the searchable keywords associated with the article are stored only in this column. Instead of using a body column and a category column, you can remove the category column and use the "body_<category>" column that stores searchable keywords. As the following example shows:--if you can adjust the schema, it's very effective ‐ each category--becomes its own column (or table), and needs to be hit--there are fewer full-text indexes. This clearly requires some explanation ... SELECT [key], [rank] from freetexttable (articles, Body_Sports, ' Ichiro ')
The performance of systems that contain large amounts of data that can be adapted to this schema (perhaps the master schema) can be significantly improved. But there are obvious limitations on when to apply multiple filters or not to apply filters. Of course, there are other ways to solve these problems. With the example above, you'll learn a way to abstract certain search criteria to a schema--actually, "spoofing" the optimizer (or rather, "becoming" the optimizer), because local optimizations are not currently present in the Full-text queries of SQL Server itself. Other performance tips The other question that people often ask me when chatting is how to page to display Full-text query results. In other words, if I were to issue a "root Beer" query, display 40 results on one Web page at a time, and only want to return 40 results on that page (for example, if I was on page three, I'd like to return only the 81st to 120th results). I have seen many ways of showing the results of pagination, but there is no way to be absolutely effective. The method that I recommend minimizes the number of Full-text query executions (in fact, only one execution for each result set to be paged out) and uses the WEB server as a simple cache. On a higher level, you simply retrieve a complete set of primary key and row-value rowsets in a full-text query (you can use the best selection in the schema and extract common filters if you want) and store it in the Web server's memory (depending on your application and load, imagine <32 The typical primary key size of the byte is added to the <4 byte's rank size [equals <36 byte], then multiplied by the normally returned result set <1000 row, and finally equals <35k. Assuming that an active cache set is returned at any given time in a <1000 active query result set, you will find that the active cache set consumes less than 35MB of memory on the WEB server-which is also acceptable. For pagination to display results, the process traverses only the array of memory stored in the WEB server and issues a SELECT to SQL Server to display only the rows and columns that need to be displayed. This goes back to the notion that Full-text queries return only primary keys and rank-SELECT (even many such queries) many times faster than Full-text queries. By combining multiple rows with a SELECT instead of a base table, and incorporating multiple other policies, you can keep more CPU cycles on your SQL Server computer and use the WEB domain more efficiently and cost-effectively. Another way to replace a WEB server-side cache is to cache the result set in SQL Server itself and define a variety of methods for browsing these results. Although this article highlights the WEB server (ASP) levelApplication programming, but the programmable capabilities of SQL Server also provide a powerful framework for generating high-performance Web search applications. Summary Microsoft SQL Server 2000 's Full-text Search feature provides a reliable, fast, and flexible way to index and query unstructured text data stored in the database. If you want to widely apply this fast, accurate search function to a variety of applications, it is necessary to make full use of its speed and accuracy to achieve a full-text search solution. By distributing compute loads and organizing data in some ingenious ways, you can save money to buy other hardware and software to get rid of the trouble of unnecessary slow queries. When developing good search applications, there are usually a number of factors and considerations to consider, and it is hoped that the information and examples provided in this article will help you learn how to build an excellent WEB search application using SQL Server 2000. Appendix A: The best choice for Full-text search improving the performance and effectiveness of full-text query is a feasible way to achieve the "best choice" system. This system is an easy way to ensure that some rows that match a particular query expression are returned before the other rows. The best choice is not complex pre-programmed logic (for example, the SharePoint Portal Server contains such logic), so it is usually the preferred approach. In this example, select the best selection and store the unique primary key and some keywords in a separate table. The FREETEXTTABLE query executes on (very small) best selection tables, and any results returned from the query are returned with the results of the FREETEXTTABLE query on the base table. Given these search conditions, all "best selection" rows will be returned first, followed by MSSearch as the most associated rows (returned in descending order). Here is a very simple sample script for creating the best choice system. Use MyDb
CREATE TABLE documenttable (ftkey int not NULL, document NTEXT) create unique index dtftkey_idx on documenttable (Ftkey)
/* Insert document HERE (all documents to be generated for full-text indexing) * *
/* Now create the best selection table and index (add the document that should always be returned first) */create table bestbets (ftkey int not null, keywords ntext) create unique index Bbftkey_ IDX on bestbets (ftkey)
First, you create a generic "all documents" table that stores all the documents you want to Full-text index. In general, the document table contains other columns, but in this article, it contains only two columns-the primary key index and the document itself. Full-text catalogs and indexes are created for document tables. It then creates a "best choice" table to store the special documents that are returned first in all Full-text queries. This table only needs to have a FULL-TEXT primary key column and the document itself, which optimizes the policy for some documents as a query target, including adding other keywords to documents that the document itself does not contain. Full-text catalogs and indexes are created for the best selection table. The best selection table and document table can share documents (the best selection documents are also stored in regular document tables, they share the same primary key value), or they can be mutually exclusive (best choice documents are stored only in the best selection table). For easy retrieval, it is easier to make the best selection table mutually exclusive to the document table-without removing the shared operation from the best selection and the collection of normal search result rows returned. On the other hand, using this method to maintain a document can be difficult to implement because in this method, you add logic to the query to delete the shared document between the returned rowset. Given the table above, you can create two stored procedures to search for the best selection table and the document table. You can use WEB server-level logic or other stored procedures to cache and display the desired results (see below for a complete, valid example of caching, display, and paging, when used with the best choice). First, create a stored procedure to retrieve the best selection row (if any): CREATE PROCEDURE bbsearch @searchTerm varchar (1024) AS
Select [Key], [rank] from freetexttable (bestbets, keywords, @searchTerm) order by [rank] desc
Make sure that the incoming search string is cleaned up to avoid the arbitrary execution of T-SQL on the server and that the string is enclosed in single quotes. In this case, using freetexttable is better than using CONTAINSTABLE because freetexttable will use the root-tracing function and find the best choice to match any search term. Next, the second stored procedure retrieves documents that match the general search criteria (if any): CREATE PROCEDURE ftsearch @searchTerm varchar (1024) AS
Select [Key], [rank] from freetexttable (documenttable, keywords, @searchTerm) order by [rank] desc
Also, make sure that you have cleaned the incoming search string and enclose the string in single quotes. When you execute these stored procedures, you should pass in the same search term in two stored procedures, first perform the best selection search, and then perform a normal full-text search. The next section provides a more comprehensive overview of how to use the best choice with other Full-text search technologies when building a WEB search application. Appendix B: Sample Applications using best choice, results paging, and valid Full-text query logic in this case, we implemented a WEB search application that took advantage of all the optimizations described in this article. We use a simple search engine solution for the online retailer catalog and assume that when traffic is high, all users expect to get results within a short response time. This example uses the best selection table and stored procedures in the previous section. This application is just a few simple examples of advanced policies that can be used to achieve optimal full-text search performance. This example uses ASP, or it can use ISAPI, asp.net, or other platforms to implement similar solutions with their own pros and cons. Session objects do not necessarily apply to all applications and, if used improperly, can pose a certain level of risk. In this case, we use session objects to implement fast and efficient caching mechanisms-and there are many other ways to implement this functionality to varying degrees. The following is the generic code for the ASP page: <% @Language = "VBScript"%><% Response.Buffer = True%>
Dim FirstRow ' first line of page display lines Dim lastrow ' The last line of Dim pageSize ' page Size (number of rows per row) Dim cn ' Connect Object Dim rs ' FT Primary key /ranked result set (reused) Dim UseCache ' use cache or hit FT (0: no use; 1: Use) Dim alldata ' The result rowset to cache Dim Bbdata ' The best selection of rows to cache Dim connect Ionstring ' SQL connection string
' Determine if you want to get data from the cache ' defaults to no, or accept the incoming data if (request). Form ("UseCache") <> "") then UseCache = Request. Form ("UseCache") ElseIf (request. QueryString ("UseCache") <> "") then UseCache = Request. QueryString ("UseCache") Else UseCache = 0end If
' Set constant pagesize = 24firstRow = 0lastRow = 23connectionString = < Enter your connection string here >
'----------------------------------------------------------------' shows simple primary key/rank matching with best selection/search terms-------- --------------------------------------------------------' Private Sub searchnpage ()
Dim P ' Loop Counter Dim numrows ' buffer/result set total number of rows
if (UseCache <> "1") Then ' get the best selection/result and cache it
Dim queryarg ' incoming query word if (request. Form ("Searchterm") <> "") then Queryarg = Request. Form ("Searchterm") ElseIf (request. QueryString ("Searchterm") <> "") then Queryarg = Request. QueryString ("Searchterm") else response. Write ("Not provided search word" & VbCrLF) Exit Sub End If
' Ideally, you should clean up the search terms here ... ' Add custom cleanup logic to prevent ' random execution of SQL
' Call CleanString (Queryarg)
' Establish a connection with SQL set cn = Server.CreateObject (' ADODB. Connection ") cn. Open connectionString
' Get the best selection match from the incoming clean string = Set rs = CN. Execute ("Exec bbsearch '" & Queryarg & "")
' If you have the best choice, get the best choice if not (Rs. EOF) Then Bbdata = Rs. GetRows End If
' Now get the normal match set rs = cn from the incoming clean string. Execute ("Exec ftsearch '" & Queryarg & "")
' If no result is returned, End if (Rs. EOF and IsEmpty (bbdata)) then response. Write ("No Matching Rows" & VbCrLF) Call Connclose Exit Sub-end If
' Otherwise, get the row if not (Rs. EOF) Then AllData = Rs. GetRows session ("results") = AllData End If
Else ' Load from cache (usecache=1)
AllData = Session ("Results")
' Here gets the row range to use if (request. Form ("FirstRow") <> "") then FirstRow = Request. Form ("FirstRow") lastrow = Firstrow+pagesize ElseIf (Request. QueryString ("FirstRow") <> "") then FirstRow = Request. QueryString ("FirstRow") LastRow = Firstrow+pagesize End If
End If ' usecache<>true
' For this application, just print out all the best choices ' (probably larger than the page size) and then page out the normal results ' here assumes that when using the cache, if there is no new best choice, ' Use the best choice previously shown if not (IsEmpty (bbdata) Then Response. Write ("Best choice:" & VbCrLf) for p = 0 To UBound (bbdata, 2) response. Write (Bbdata (0,p) & "" & Bbdata (1,p) & VbCrLf) next response. Write (VbCrLf) End If
' Return search results (probably only best choice) if not (IsEmpty (alldata)) then if UBound (AllData, 2) < lastrow then lastrow = UBound (A Lldata, 2) End If
Response. Write ("Search results:" & VbCrLf)
For p = firstrow to Lastrowresponse.write (AllData (0,p) & "" & AllData (1,p) & VbCrLf) Next End If ' N OT (IsEmpty (ALLDATA))
'----------------------------------------------------------------' closes and clears the connection object '----------------------------------------------------------------' Private Sub connclose Rs. Close Set rs = Nothing cn. Close Set cn = NothingEnd Sub
As shown in the two code examples above, it does not take much effort to create a WEB application that performs a valid Full-text query, which is done with the best choice, and caches and pages to display the results. With minimal overhead, you can add logic to provide additional data, enhance the appearance of the best choice, and navigate through search results (in addition, it is strongly recommended that you implement other rigorous logic for error handling, security settings, and cleanup of incoming data). With the advanced recommendations and examples above, it is easy to design and implement a fast, scalable WEB search application using SQL Server 2000 Full-text search.
Appendix C: Resource Full-text Search Deployment (English) http://support.microsoft.com/default.aspx?scid=/support/sql/content/ 2000papers/fts_white%20paper.asp is the best reference for those who first contact Full-text search. Describes the padding method and hardware and software requirements, and provides tips, tricks, and other documentation for using SQL Server 2000 Full-text search. Full-Text Search public newsgroups (microsoft.public.sqlserver.fulltext) find an ideal place for answers to full-text search questions and useful tips and tricks. Full-Text Search newsgroups are sites frequented by the SQL Server development team and knowledgeable Microsoft MVP.
This article is an English version of an article which is originally in the Chinese language on aliyun.com and is provided for information purposes only. This website makes no representation or warranty of any kind, either expressed or implied, as to the accuracy, completeness ownership or
reliability of the article or any translations thereof. If you have any concerns or complaints relating to the article, please send an email, providing a detailed description of the concern or
complaint, to firstname.lastname@example.org. A staff member will contact you within 5 working days. Once verified, infringing content will be removed immediately.
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
and provide relevant evidence. A staff member will contact you within 5 working days.