Extension:Cargo/Storing data

在Cargo中，创建数据结构、存储数据都仅通过模板完成。 
任何使用Cargo的模板都需要包含对解析器函数#cargo_declare和#cargo_store的调用，或者较罕见的是调用#cargo_attach和#cargo_store。
#cargo_declare定义了数据表的字段，#cargo_store将数据存入数据表，#cargo_attach指定将模板数据存入事先在其他地方定义过了的数据表。
==声明一个表==
需要将数据存储在表中的模板，要么声明该表，要么将自身 "附着" 在其他地方声明过的表。
由于通常情况下表和模板是一一对应的，大多数使用Cargo的模板都会声明自己的表。
声明通过解析函数 #cargo_declare 完成。 
这个函数通过如下语法调用： 
{{#cargo_declare:
_table = table_name
|field_1 = field description 1
|field_2 = field description 2
...etc.
}}
表名和字段名都不能包含空格或破折号，但你可以使用下划线、CamelCase式大小写等。
下划线不能用于表和字段名称的开头或结尾。 
字段描述必须以字段的类型开头，很多情况下描述内容只是类型。
Cargo中预定义了以下类型： 
字段类型 	描述 	是否为不可索引
Page 	存储wiki中页面的名称 （默认最大大小：300字符） 	
String 	存储标准的文本，非维基文本 （默认最大大小：300字符） 	
Text 	存储标准的文本，非维基文本，用于更长的值 	✔
Integer 	存储整数 	
Float 	存储实数，可以非整数 	
Date 	存储日期，不带时间 	
Start date,End date 	类似于Date，但是用于存储一段时间的开始和结尾 表可以不包含Start date和End date字段，也可以只包含两者之一。 	
Datetime 	存储日期和时间 	
Start datetime,End datetime	与Start date或End date类似，但是包含时间。 	
Boolean 	存储布尔值，值只能是1或0，或者“yes”“no”（查询Cargo指定的字符串值的信息参见此段） 	
Coordinates 	存储地理坐标 	
Wikitext string 	存储短文本，用于被MediaWiki解析器解析 （默认最大大小：300字符） 	
Wikitext 	存储长文本，用于被MediaWiki解析器解析 	✔
Searchtext 		存储可以被搜索的文本，使用 MATCHES 命令 （需要MySQL 5.6+或MariaDB 5.6+） 	
File 	存储wiki中已上传的文件或图像的名字（类似于Page，但是不需要指定“File:”命名空间） （默认最大大小：300字符） 	
URL 	存储URL （默认最大大小：300字符） 	
Email 	存储电子邮件地址 （默认最大大小：300字符） 	
Rating 	存储“评分”值，比如通常为1到5之间的整数 	
指定的任何其他类型都将被视为“字符串”类型。
未索引类型的字段查询或连接的速度要慢得多。
字段也可以存储以上类型的列表。
要定义一个这样的列表，类型值应该是这样子：“List (分隔符 ) of 类型”。
例如，如果要有叫做“Authors”的字段，存储由逗号隔开的字符串值，你可以在$cargo_declare调用中使用以下参数： 
|Authors=<translate nowrap> List (,) of String
===字段参数===
描述字符串也可以有额外的参数，这些都包含在类型标识符后的括号中，用分号隔开。
当前允许的参数有： 
参数 	描述
size= 	For fields of type "Page", "String", "Wikitext string", "File", "URL" and "Email", sets the size of this field, i.e. the number of characters; the default is set by the global variable $wgCargoDefaultStringBytes, which in turn has a default value of 300 (although it can be modified in LocalSettings.php).
hierarchy 	Specifies that the field holds a hierarchy of values, as defined in the "allowed values" parameter (see next item).
allowed values=	A set of allowed values that a field can have. (This is usually only done for fields of type "String" or "Page".) If "hierarchy" is not specified, this should simply be a set of comma-separated values. If "hierarchy" is specified, the values should be defined using the syntax of a bulleted list. In brief: every value should be on its own line, each line should start with at least one "*", the first line should start with exactly one "*", and the number of "*" should increase by no more than one at a time.
:For example, to define a field called "Color" that has three allowed values, you could have the following declaration:
|Color=String (size=10;allowed values=Red,Blue,Yellow)
:Meanwhile, to define a field called "Main ingredient" that is a hierarchy, you could have the following declaration:
|Main_ingredient = String (hierarchy;allowed values=*Fruits
**Mangoes
**Apples
*Vegetables
**Root vegetables
***Carrots
***Turnips
**Peppers)
参数 	描述
link text= 	For fields of type "URL", sets text that would be displayed as a link to that URL. By default the entire URL is shown.
hidden 	Takes no value. If set, the field is not listed in Special:Drilldown, although it is still queriable.
mandatory 	Takes no value. If set, the field is declared as mandatory, i.e. blank values are not allowed.
unique 	Takes no value. If set, all values for the field must be unique - a value that already exists for that field in the table will not be saved.
regex= 	Sets a regular expression for this field, which all values must match. For example if "regex=T\d+" is set, values for that field must consist of the letter "T" followed by one or more numerals.
dependent on=	Takes in the name of another field in this table, to specify that this field should only be displayed in Special:Drilldown once the user has selected a value for that field.
===其他的#cargo_declare参数===
除了表的名称和字段之外，以下参数也可以添加到#cargo_declare中： 
* _parentTables - for setting one or more other Cargo tables as the "parent tables" of this table. This is used within Special:Drilldown, to let the user filter on fields from additional Cargo tables that are tied in some way to this one. It takes the following syntax:
|_parentTables= tableName1(_localField=localFieldName, _remoteField=remoteFieldName, _alias=tableAlias); tableName2(...); ...
: Here, 'tableName1' is the name of the table you want to declare as the parent table. '_localField' and '_remoteField' specify the fields in the two tables that need to be joined on (the default values for both are "_pageName"). If '_alias' is defined, then that will be displayed in the drilldown instead of the parent table's name.
:例子： This drilldown display shows additional drilldown fields from a parent table, "Items" (listed as "Item) (template here)
* _drilldownTabs - for setting custom drilldown tabs in Special:Drilldown page. It can be declared like this:
|_drilldownTabs= Tab1(format=list;delimiter=\;;fields=A,B,C), Tab2(format=table; fields=A,C,D)
:where 'Tab1' is the display name of the tab, 'format' parameter takes the desired format name and after that you can add all the parameters needed for that format and then 'fields' holds the set of fields to be displayed.
:例子： This drilldown display also shows custom tabs (template here)
#cargo_declare also displays a link to the Special:CargoTables page for viewing the contents of this database table.
==附着于另一个表==
In some cases, you may want more than one template to store their data to the same Cargo table.
In that case, only one of the templates should declare the table, while the others should simply "attach" themselves to that table, using the parser function #cargo_attach.
This function is called with the following syntax:
{{#cargo_attach:
_table = table_name
}}
A template should have no more than one call to #cargo_attach (and no more than one call to #cargo_declare, for that matter).
Any template that contains a call to #cargo_store should also call either #cargo_declare or #cargo_attach.
==在一个表中存储数据==
A template that declares a table or attaches itself to one should also store data in that table.
This is done with the parser function #cargo_store.
Unlike #cargo_declare and #cargo_attach, which apply to the template page itself and thus should go into the template's <noinclude> section, #cargo_store applies to each page that calls that template, and thus should go into the template's <includeonly> section.
This function is called with the following syntax:
{{#cargo_store:
_table = table_name
|field_1 = value 1
|field_2 = value 2
...etc.
}}
The field names must match those in the #cargo_declare call elsewhere in the template.
The values will usually, but not always, be template parameters; but in theory they could hold anything.
For fields whose value is a template parameter, and where the name of the template parameter is the same as the name of the Cargo field (other than the presence of underscores instead of spaces), the field can be left out of the #cargo_store call; so, in many cases, the call could instead simply look like:
{{#cargo_store:
_table = table_name
}}
In fact, not even the table name really needs to specified; so in many cases the call could even look like:
{{#cargo_store:}}
However, this is slightly less efficient (and maybe more confusing to readers) than specifying the table name.
===存储循环事件===
Special handling exists for storing recurring events, which are events that happen regularly, like birthdays or weekly meetings.
For these, the parser function #recurring_event exists.
It takes in a set of parameters for a recurring event (representing the start date, frequency etc.), and simply prints out a string holding a list of the dates for that event.
It is meant to be called within #cargo_store (for a field defined as holding a list of dates), and #cargo_store will then store the data appropriately.
#recurring_event is called with the following syntax:
{{#recurring_event:
start=start date
|end=end date
|unit=day, week, month or year
|period=some number, representing the number of "units" between event instances (default is 1)
|include=list of dates, to be included in the list
|exclude=list of dates to exclude
|delimiter=delimiter for dates (default is ';')
}}
Of these parameters, only "start=" and "unit=" are required.
By default, if no end date is set, or if the end date is too far in the future, #recurring_event stores 50 instances of the event.
To change this, you can add a setting for in LocalSettings.php, under the inclusion of Cargo.
For instance, to set the number to 100, you would add the following:
$wgCargoRecurringEventMaxInstances = 100;
If working with recurring events, declare the type of the field of the field to be List (;) of Date.
==示例==
你能看到两个模板，使用的 #cargo_declare 和 #cargo_store 在 这里 和 这里。
==创建或重新创建一个表==
No data is actually generated or modified when a template page containing a #cargo_declare call is saved.
Instead, the data must be created or recreated in a separate process.
There are two ways to do this:
===通过网页===
从（声明）模板的页面，选择标签动作调用“创建数据”或者“重新创建数据”。
这将打开一个界面，其中包含复选框“重建数据至替换表格，保持旧有数据用于查询”。
（那个复选框只会出现在如果询问的 Cargo 表已经存在。）
一旦你点了“确定”，下列之一将发生：
# If the checkbox was selected, a "replacement table" will be created, while the current table remains unaffected. This replacement table can be viewed by anyone, but its data will not be used in queries. (In the database, the actual table will have a name like "cargo__tableName__NEXT".) If/when you think this replacement table is ready to be used, you can click on the "Switch in table" link at Special:CargoTables. This link will delete the current Cargo table and rename the replacement table so that it becomes the official table. Conversely, if you don't want to use the replacement table, you can click on the "Delete" link for it.
# If the checkbox was not selected, the current table will be deleted immediately, and a new version will get created.
# If the checkbox was not there, it means that this is a new table. In that case, the table will be created.
In all three cases, MediaWiki jobs are used to cycle through all the relevant pages and recreate the data - a separate job is created for each page.
This can be a lengthy process for large tables, which is why using the "replacement table" approach is recommended for large tables - it avoids a "down time" period when the table is mostly empty.
Depending on the MediaWiki configuration, a call to MediaWiki's runJobs.php script may be useful or even necessary for these jobs to actually start.
If any templates contain #cargo_attach, they too will get a "Create data" or "Recreate data" tab.
If this tab is selected and activated, it will not drop and recreate the database table itself; instead, it will only recreate those rows in the table that came from pages that call that template.
====权限====
The ability to create/recreate data is available to users with the 'recreatecargodata' permission, which by default is given to sysops.
You can give this permission to other users; for instance, to have a new user group, 'cargoadmin', with this ability, you would just need to add the following to LocalSettings.php:
$wgGroupPermissions['cargoadmin']['recreatecargodata'] = true;
Once a table exists for a template, any page that contains one or more calls to that template will have its data in that table refreshed whenever it is resaved; and new pages that contain call(s) to that template will get their data added in when the pages are created.
===命令行脚本===
If you have access to the command line, you can also recreate the data by calling the script cargoRecreateData.php, located in Cargo's /maintenance directory.
It can be called in one of two ways:
命令 	描述
php cargoRecreateData.php 	Recreates the data for all Cargo tables in the system
php cargoRecreateData.php --table tableName	Recreates the data for the one specified Cargo table.
In addition, the script can be called with the --quiet flag, which turns off all printouts.
For full usage information, call it with --help.
==存储页面数据==
You can create an additional Cargo table that holds "page data": data specific to each page in the wiki, not related to infobox data.
This data can then be queried either on its own or joined with one or more "regular" Cargo tables.
The table is named "_pageData", and it holds one row for every page in the wiki.
You must specify the set of fields you want the table to store; by default it will only hold the five standard Cargo fields (_pageName, _pageTitle, _pageNamespace, _pageID and _ID: see Database storage details).
To include additional fields, add to the array $wgCargoPageDataColumns in LocalSettings.php, below the line that installs Cargo.
Currently there are seven more fields that can be added to the _pageData table; here are the fields, and the call to add each one:
字段 	描述 	LocalSettings.php call
_creationDate 	The date/time the page was created 	$wgCargoPageDataColumns[] = 'creationDate';
_modificationDate 	The date/time the page was last modified 	$wgCargoPageDataColumns[] = 'modificationDate';
_creator 	The username of the user who created the page 	$wgCargoPageDataColumns[] = 'creator';
_fullText 	The (searchable) full text of the page 	$wgCargoPageDataColumns[] = 'fullText';
_categories 	The categories of the page (a list, queriable using "HOLDS"). Note that spaces are stored as underscores.	$wgCargoPageDataColumns[] = 'categories';
_numRevisions 	The number of edits this page has had 	$wgCargoPageDataColumns[] = 'numRevisions';
_isRedirect 	Whether this page is a redirect 	$wgCargoPageDataColumns[] = 'isRedirect';
_pageNameOrRedirect	The target of the page if it's a redirect, otherwise the page name 	$wgCargoPageDataColumns[] = 'pageNameOrRedirect';
Once you have specified which fields you want the table to hold, go to the Cargo /maintenance directory, and make the following call to create, or recreate, the _pageData table:
php setCargoPageData.php
To recreate with replacement, add a --replacement flag:
php setCargoPageData.php --replacement
The replacement table can then be switched in normally using the Special:CargoTables interface.
If you want to get rid of this table, call the following instead:
php setCargoPageData.php --delete
You do not need to call the "--delete" option if you are planning to recreate the table; simply calling setCargoPageData.php will delete the previous version.
==存储文件数据==
Similarly to page data, you can also automatically store data for each uploaded file.
This data gets put in a table called "_fileData", which holds one row for each file.
This table again has its own settings array, to specify which columns should be stored, called $wgCargoFileDataColumns.
There are currently five columns that can be set:
字段 	描述 	LocalSettings.php call
_mediaType 	The media type, or MIME type, of each file, like "image/png" 	$wgCargoFileDataColumns[] = 'mediaType';
_path 	The directory path of the file on the wiki's server 	$wgCargoFileDataColumns[] = 'path';
_lastUploadDate	The date/time at which the file was last uploaded 	$wgCargoFileDataColumns[] = 'lastUploadDate';
_fullText 	The full text of the file; this is only stored for PDF files 	$wgCargoFileDataColumns[] = 'fullText';
_numPages 	The number of pages in the file; this is only stored for PDF files	$wgCargoFileDataColumns[] = 'numPages';
To store the full text of PDF files, you need to have the pdftotext utility installed on the server, and then add the following to LocalSettings.php:
:$wgCargoPDFToText = '...path to file.../pdftotext';
pdftotext is available as part of several different packages.
if you have the PdfHandler extension installed (and working), you may have pdftotext installed already.
To store the number of pages, you need to have the pdfinfo utility installed on the server, and then add the following to LocalSettings.php:
:$wgCargoPDFInfo = '...path to file.../pdfinfo';
Once you have specified which fields you want the table to hold, go to the Cargo /maintenance directory, and make the following call to create, or recreate, the _fileData table:
php setCargoFileData.php
==数据库存储细节==
When the data for a template is created or recreated, a database table is created in the Cargo database that (usually) has one column for each specified field.
This table will additionally hold the following columns:
字段 	描述
_pageName 	Holds the name of the page from which this row of values was stored.
_pageTitle 	Similar to _pageName, but leaves out the namespace, if there is one.
_pageNamespace	Holds the numerical ID of the namespace of the page from which this row of values was stored.
_pageID 	Holds the internal MediaWiki ID for that page.
_ID 	Holds a unique ID for this row.
===存储列表===
For fields that have lists of values, the handling is more complex: a whole separate database table is created to hold all the individual values for this field.
This table will get the name "MainTableName__FieldName" (e.g. "Books__Authors"), and it will have the following fields:
字段 	描述
_rowID 	Holds the ID of the row (i.e., _ID) in the main table that this value corresponds to.
_value 	Holds the actual, individual value.
_position	Holds the position of this value in the list (can be 1, 2, etc.)
So if an "Authors" field contained three values, the "Books__Authors" table would have three rows corresponding to that one page.
There's one more complication for list fields: the corresponding field for a list field in the database table will not actually be given that name, but will rather be called "FieldName__full", e.g. "Authors__full".
This is to enable the "true" field name to serve as a "virtual" field within the #cargo_query call, to make querying on the field values table easier (see 'The "HOLDS" command').
===存储层次结构===
For fields that have a set of allowed values that is defined as being a hierarchy, a separate database table is created to store the whole set of allowed values.
This table will get the name "MainTableName__FieldName__hierarchy" (e.g.
"Books__Genre__hierarchy"), and it will have the following fields:
字段 	描述
_value	The allowed value.
_left 	The number of the leftmost node represented by this value.
_right	The number of the rightmost node represented by this value.
For an explanation of this method of storage, see the Wikipedia article "Nested set model".
===存储文件名称===
If a table has one or more fields of type "File", an additional table is created - for use in searching on files within Special:Drilldown - with the name "MainTableName__files" (e.g. "Books__files"), with the following fields:
字段 	描述
_pageName 	The name of the page from which this row of values was stored.
_pageID 	The internal MediaWiki ID for the page.
_fieldName	The name of the relevant field of type "File".
_fileName 	The value of the field, i.e. the name of an uploaded file.
===存储坐标===
For fields of type 'Coordinates', like for fields that hold a list of values, no database field is created with the actual specified field name.
Instead, the following three fields are created:
字段 	描述
fieldName__full	Holds the coordinates as written in the page
fieldName__lat 	Holds the latitude from the coordinates, as a float
fieldName__lon 	Holds the longitude from the coordinates, as a float
If the coordinates cannot be parsed, the "__full" field still gets the value, but the "__lat" and "__lon" fields are set to null.
===存储日期===
For fields of type 'Date' or 'Datetime', an extra field is created that is named "fieldName__precision".
It holds an integer value representing the "precision" of each date value, i.e. whether it holds a full date, only a year, etc.
The possible values are:
值 	描述
0 	Date and time (can only occur for 'Datetime' fields)
1 	Date only
2 	Year and month only
3 	Year only
==存储 Flex Diagrams 数据==
Flex Diagrams 扩展让用户在百科页面内定义（并显示）图表。
如果 Cargo 和 Flex Diagrams 都安装在同一个百科上，你能把那些图表中的一些数据存储在特殊 Cargo 表中，以便浏览和查询数据。
能存储两种图表类型的数据：BPMN 图表和甘特图。
不像 Cargo 的标准特殊表，_pageData 和 _fileData，你不能指定设置哪些列——它们都是。
===业务流程图===
关于业务流程建模符号（BPMN）图表的数据存储在表 _bpmnData。
这个表能通过在 Cargo /maintenance 目录调用下列生成：
php setCargoBPMNData.php
This table holds the following columns:
字段 	描述
_BPMNID 	The internal ID of a component
_name 	The external name assigned to the component
_type 	The type of the component; one of 'task', 'exclusiveGateway', 'sequenceFlow', or 'startEvent'
_connectsTo	The IDs of the components this component connects to
_annotation	The annotation of this component.
===甘特图===
关于甘特图的数据存储在表 _ganttData。
这个表能通过在 Cargo /maintenance 目录调用下列生成：
php setCargoGanttData.php
This table holds the following columns:
字段 	描述
_localID 	The internal ID of a task
_name 	The name of the task
_startDate	The start date of the task
_endDate 	The end date of the task
_progress 	A decimal value (between 0 and 1) representing the progress of the task
_parent 	The ID of the parent task, if any
_linksToBB	A list of IDs of tasks whose beginnings are connected to this task's beginning
_linksToBF	A list of IDs of tasks whose ends are connected to this task's beginning
_linksToFB	A list of IDs of tasks whose beginnings are connected to this task's end
_linksToFF	A list of IDs of tasks whose ends are connected to this task's end