]> git.evergreen-ils.org Git - working/Evergreen.git/blob - 2.0/admin/migratingdata_2.0.xml
More on Fast Add
[working/Evergreen.git] / 2.0 / admin / migratingdata_2.0.xml
1 <?xml version='1.0' encoding='UTF-8'?>\r
2 <chapter xmlns="http://docbook.org/ns/docbook" xmlns:xi="http://www.w3.org/2001/XInclude"\r
3             xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:id="migratingdata" >\r
4         <info>          \r
5         <title>Migrating Data</title>\r
6                 <abstract>\r
7                         <para>Migrating data into Evergreen can be one of the most daunting tasks for an administrator. This chapter will explain some procedures to help to migrate \r
8                         bibliographic records, copies and patrons into the Evergreen system. This chapter requires advanced ILS Administration experience, knowledge of Evergreen data structures, \r
9                         as well as knowledge of how to export data from your current system or access to data export files from your current system.</para>\r
10                 </abstract>\r
11         </info>    \r
12         <section xml:id="migratingbibrecords">\r
13                 <title>Migrating Bibliographic Records</title>\r
14                 <indexterm><primary>migrating</primary><secondary>importing bibliographic records</secondary></indexterm>\r
15                 <para>\r
16                 One of the most important and challenging  tasks is migrating your bibliographic records to a new system. The procedure may be different depending on the system from which you \r
17                 are migrating  and the content of the marc records exported from the existing system. The procedures in this section deal with the process once the data from the existing system \r
18                 is exported into marc records. It does not cover exporting data from your existing non-Evergreen system.</para>\r
19                 <para>Several tools for importing bibliographic records into Evergreen can be found in the Evergreen installation folder \r
20                 (<filename class="directory">/home/opensrf/Evergreen-ILS-1.6.1.6/Open-ILS/src/extras/import/</filename> ) and are also available from the Evergreen repository \r
21                 (<link xl:href="http://svn.open-ils.org/trac/ILS/browser/branches/rel_1_6_1/Open-ILS/src/extras/import" xl:title="import scripts - Evergreen repository">\r
22                 http://svn.open-ils.org/trac/ILS/browser/branches/rel_1_6_1/Open-ILS/src/extras/import</link>).</para> \r
23                 <simplesect>\r
24                         <title>Converting MARC records to Evergreen BRE JSON format</title>\r
25                         <indexterm><primary>BRE JSON</primary></indexterm>\r
26                         <para>If you are starting with MARC records from your existing system or another source, use the marc2bre.pl script to create the JSON representation of a bibliographic \r
27                         record entry (hence bre) in Evergreen. <filename>marc2bre.pl</filename> can perform the following functions:</para>\r
28                         <itemizedlist> \r
29                                 <listitem><para>Converts <systemitem>MARC-8</systemitem> encoded records to <systemitem>UTF-8</systemitem> encoding</para></listitem>\r
30                                 <listitem><para>Converts <systemitem>MARC21</systemitem> to <systemitem>MARCXML21</systemitem></para></listitem>\r
31                                 <listitem><para>Select the unique record number field (common choices are '035' or '001'; check your records as you might be surprised how a supposedly unique field \r
32                                 actually has duplicates, though marc2bre.pl will select a unique identifier for subsequent duplicates)</para></listitem>\r
33                                 <listitem><para>Extracts certain pertinent fields indexing and display purposes (along with the complete MARCXML21 record)</para></listitem>\r
34                                 <listitem><para>Sets the ID number of the first record from this batch to be imported into the biblio.record_entry table (hint - run the following \r
35                                 <systemitem>SQL</systemitem> to determine what this number should be to avoid conflicts:</para>\r
36 <screen>\r
37 <userinput>psql -U postgres evergreen</userinput>\r
38 <userinput> # SELECT MAX(id)+1 FROM biblio.record_entry;</userinput>\r
39 </screen>\r
40                         </listitem>\r
41                         <listitem>\r
42                                 <para>If you are processing multiple sets of MARC records with <command>marc2bre.pl</command>before loading the records into the database, you will need to keep track \r
43                                 of the starting ID number for each subsequent batch of records that you are importing. For example, if you are processing three files of MARC records with 10000 \r
44                                 records each into a clean database, you would use <option>–startid 1</option>, <option>–startid 10001</option>, and <option>–startid 20001</option> \r
45                                 parameters for each respective file.</para>\r
46                         </listitem>\r
47                         <listitem>\r
48                                 <para>Ignore <quote>trash</quote> fields that you do not want to retain in Evergreen</para>\r
49                         </listitem>\r
50                         <listitem>\r
51                                 <para>If you use <filename>marc2bre.pl</filename> to convert your MARC records from the <systemitem>MARC-8</systemitem> encoding to the UTF-8 encoding, it relies\r
52                                  on the <systemitem>MARC::Charset Perl</systemitem> module to complete the conversion. When importing a large set of items, you can speed up the process by using a \r
53                                 utility like <systemitem>marc4j</systemitem> or <systemitem>marcdumper</systemitem> to convert the records \r
54                                 to <systemitem>MARC21XML</systemitem> and <systemitem>UTF-8</systemitem> before running them through <command>marc2bre.pl</command> with the \r
55                                 <option>–marctype=XML</option> flag to tell <command>marc2bre.pl</command> that the records are already in <systemitem>MARC21XML</systemitem> format with \r
56                                 the <systemitem>UTF-8 </systemitem>encoding. If you take this approach, due to a current limitation of <systemitem>MARC::File::XML</systemitem> you have to do a \r
57                                 horrible thing and ensure that there are no namespace prefixes in front of the element names. <filename>marc2bre.pl</filename> cannot parse the following \r
58                                 example:</para>\r
59 \r
60 <programlisting language="xml">\r
61 <![CDATA[\r
62 \r
63 <?xml version="1.0" encoding="UTF-8" ?>\r
64 <marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" \r
65   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \r
66   xsi:schemaLocation="http://www.loc.gov/MARC/slim \r
67 http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">\r
68   <marc:record>\r
69     <marc:leader>00677nam a2200193 a 4500</marc:leader>\r
70     <marc:controlfield tag="001">H01-0000844</marc:controlfield>\r
71     <marc:controlfield tag="007">t </marc:controlfield>\r
72     <marc:controlfield tag="008">060420s1950    xx            000 u fre d</marc:controlfield>\r
73     <marc:datafield tag="040" ind1=" " ind2=" ">\r
74       <marc:subfield code="a">CaOHCU</marc:subfield>\r
75       <marc:subfield code="b">fre</marc:subfield>\r
76     </marc:datafield>\r
77 ...\r
78 ]]>;\r
79 </programlisting>\r
80                         \r
81                         <para>But marc2bre.pl can parse the same example with the namespace prefixes removed:</para>\r
82 <programlisting language="xml">\r
83 <![CDATA[\r
84 <?xml version="1.0" encoding="UTF-8" ?>\r
85 <collection xmlns:marc="http://www.loc.gov/MARC21/slim" \r
86   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \r
87   xsi:schemaLocation="http://www.loc.gov/MARC/slim \r
88 http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">\r
89   <record>\r
90     <leader>00677nam a2200193 a 4500</leader>\r
91     <controlfield tag="001">H01-0000844</controlfield>\r
92     <controlfield tag="007">t </controlfield>\r
93     <controlfield tag="008">060420s1950    xx            000 u fre d</controlfield>\r
94     <datafield tag="040" ind1=" " ind2=" ">\r
95       <subfield code="a">CaOHCU</subfield>\r
96       <subfield code="b">fre</subfield>\r
97     </datafield>\r
98 ...\r
99 ]]>;\r
100 </programlisting>\r
101                                 </listitem>\r
102                         </itemizedlist>\r
103                 </simplesect>\r
104                 <simplesect>\r
105                         <title>Converting Records for Import into PostgreSQL</title>\r
106                         <indexterm><primary>migrating</primary><secondary>import into PostgreSQL</secondary></indexterm>\r
107                         <para>Once you have your records in Open-ILS <systemitem>JSON</systemitem> ingest format, you then need to use <command>pg_loader.pl</command> to convert these records into a \r
108                         set of <systemitem>SQL</systemitem> statements that you can use to \r
109                         load the records into PostgreSQL. The <option>–order</option> and <option>–autoprimary</option> command line options (bre, mrd, mfr, etc) map to class IDs defined in \r
110                         <filename>/openils/conf/fm_IDL.xml</filename>.</para>\r
111                 </simplesect>           \r
112                 <simplesect>\r
113                         <title>Adding Metarecords to the Database</title>\r
114                         <indexterm><primary>migrating</primary><secondary>adding metarecords</secondary></indexterm>\r
115                         <para>One you have loaded the records into PostgreSQL, you can create metarecord entries in the <link linkend="metabib.table.metarecord">metabib.metarecord</link> table by                             running the following <systemitem>SQL</systemitem>:</para>\r
116 <screen>\r
117 <userinput>psql evergreen</userinput>\r
118 <userinput># \i /home/opensrf/Evergreen-ILS-1.6*/src/extras/import/quick_metarecord_map.sql</userinput>\r
119 </screen>\r
120                         <para>Metarecords are required to place holds on items, among other actions.</para>\r
121                 </simplesect>   \r
122         </section>\r
123 \r
124 \r
125 \r
126 <section xml:id="migrating_records_using_migration_tools">\r
127                 <title>Migrating Bibliographic Records Using the ESI Migration Tools</title>\r
128                 <indexterm><primary>migrating</primary><secondary>bibliograohic records</secondary></indexterm> \r
129                 <para>The following procedure explains how to migrate bibliographic records from marc records into Evergreen. This is a general guide and will need to be adjusted for your \r
130                 specific environment. It does not cover exporting records from specific proprietary ILS \r
131                 systems. For assistance with exporting records from your current system please refer to the manuals for your system or you might try to ask for help from the \r
132                 <link linkend="more_info">Evergreen community</link>.</para>\r
133                 \r
134                 <procedure>\r
135                         <step>\r
136                                 <para>Download the Evergreen <link xl:href="http://git.esilibrary.com/?p=migration-tools.git;a=summary" \r
137                                 xl:title="Equinox migration utilities">migration utilities</link> from the git repository.</para>\r
138                                 <para>Use the command <command>git clone git://git.esilibrary.com/git/migration-tools.git</command> to clone the migration tools.</para>\r
139                                  <para>Install the migration tools:</para>\r
140 <screen>\r
141 <userinput>\r
142 <![CDATA[\r
143 cd migration-tools/Equinox-Migration\r
144 perl Makefile.PL\r
145 make\r
146 make test\r
147 make install\r
148 ]]>\r
149 </userinput>\r
150 </screen>\r
151 </step> \r
152                         <step>\r
153                                 <para>Add environmental variables for migration and import tools. These paths must point to:\r
154                                         <itemizedlist>\r
155                                                 <listitem>the import perl scripts bundled with Evergreen </listitem>\r
156                                                 <listitem>the folder where you extracted the migration tools</listitem>\r
157                                                 <listitem>the location of the Equinox-Migration perl modules </listitem>\r
158                                                 <listitem>the location of the Evergreen perl modules (e.g. perl5)</listitem>\r
159                                         </itemizedlist>\r
160                                 </para> \r
161 <screen>\r
162 <userinput>export PATH=[<emphasis class="italic">path to Evergreen</emphasis>]/Open-ILS/src/extras/import: \\r
163 /[<emphasis class="italic">path to migration-tools</emphasis>]/migration-tools:$PATH:.\r
164 export PERL5LIB=/openils/lib/perl5: \ \r
165 /[<emphasis class="italic">path to migration-tools</emphasis>/Equinox-Migration/lib\r
166 </userinput>\r
167 </screen>\r
168 </step>\r
169 <step>\r
170                                 <para>Dump marc records into MARCXML using <systemitem>yaz-marcdump</systemitem></para>\r
171 \r
172 <screen>\r
173 <userinput>\r
174 <![CDATA[\r
175 echo '<?xml version="1.0" encoding="UTF-8" ?>' > imported_marc_records.xml\r
176 yaz-marcdump -f MARC-8 -t UTF-8 -o marcxml imported_marc_records.mrc >> imported_marc_records.xml\r
177 ]]>\r
178 </userinput>\r
179 </screen>\r
180 </step> \r
181 <step>\r
182                                 <para>Test validity of XML file using <systemitem>xmllint</systemitem></para>\r
183 <screen>\r
184 \r
185 <userinput>\r
186 <![CDATA[\r
187  xmllint --noout imported_marc_records.xml 2> marc.xml.err\r
188 ]]>\r
189 </userinput>\r
190 </screen>\r
191 </step> \r
192 \r
193 <step>\r
194                                 <para>Clean up the marc xml file using the <systemitem>marc_cleanup</systemitem> utility:</para>\r
195 <screen>\r
196 <userinput>\r
197 marc_cleanup --marcfile=imported_marc_records.xml --fullauto [--renumber-from #] -ot 001\r
198 </userinput>    \r
199 </screen>\r
200                                 <para>The <option>--renumber-from</option> is required if you have bibliographic records already in your system. Use this to set the starting id number higher \r
201                                 then the last id in the biblio.record_entry table. The marc_cleanup command will generate a file called <filename>clean.marc.xml</filename></para>\r
202 </step>\r
203 <step>\r
204                                 <para>Create a fingerprinter file using the <systemitem>fingerprinter</systemitem> utility:</para>\r
205 <screen>\r
206 <userinput>\r
207 fingerprinter -o incumbent.fp -x incumbent.ex clean.marc.xml\r
208 </userinput>                    \r
209 </screen>\r
210                                 <para><systemitem>fingerprinter</systemitem> is used for deduplification of the incumbent records. The <option>-o</option> option specifies the \r
211                                 output file and the <option>-x</option> option is used to specify the error output file.</para>\r
212 </step>\r
213 <step>\r
214                                 <para>Create a fingerprinter file for existing Evergreen bibliographic records using the <systemitem>fingerprinter</systemitem> utility if you \r
215                                 have existing bibliographic records in your system previously imported:</para>\r
216 <screen>\r
217 <userinput>\r
218 fingerprinter -o production.fp -x production.fp.ex --marctype=MARC21 existing_marc_records.mrc \\r
219 --tag=901 --subfield=c\r
220 </userinput>\r
221 </screen>\r
222                                 <para><systemitem>fingerprinter</systemitem> is used for deduplification of the incumbant records.</para>\r
223 </step>\r
224 \r
225 <step>\r
226                                 <para>Create a merged fingerprint file removing duplicate records.</para>\r
227 <screen>\r
228 <userinput>\r
229 cat cat production.fp incumbent.fp | sort -r > dedupe.fp\r
230 match_fingerprints [-t start id] -o records.merge dedupe.fp\r
231 </userinput>\r
232 </screen>\r
233 </step>\r
234 \r
235 <step>\r
236                                 <para>Create a new import XML file using the <systemitem>extract_loadset</systemitem> utility</para>\r
237 <screen>\r
238 <userinput>extract_loadset -l 1 -i clean.marc.xml -o merged.xml records.merge</userinput>\r
239 </screen>\r
240 </step>\r
241 \r
242 <step>\r
243                                 <para>Extract all of the currently used TCN's an generate the .bre and .ingest files to prepare for the bibliographic record load.</para>\r
244 <screen>\r
245 <userinput>\r
246 psql -U evergreen -c "select tcn_value from biblio.record_entry where not deleted" \\r
247 | perl -npe 's/^\s+//;' > used_tcns\r
248 marc2bre.pl --idfield 903 [--startid=#] --marctype=XML -f final.xml \\r
249 --used_tcn_file=used_tcns > evergreen_bre_import_file.bre\r
250 </userinput>\r
251 </screen>\r
252                                 <note>\r
253                                         <para> The option <option>--startid</option> needs to match the start id used in earlier steps and must be higher than largest id value \r
254                                         in the biblio.record_entry table. the option <option>--idfield</option> should match the marc datafield used to store your records ids.</para>\r
255                                 </note>\r
256 </step>\r
257 \r
258 <step>\r
259                                 <para>Ingest the bibliographic records into the Evergreen database.</para>\r
260 <screen>\r
261 <userinput>\r
262 <![CDATA[\r
263 parallel_pg_loader.pl \\r
264 -or bre \\r
265 -or mrd \\r
266 -or mfr \\r
267 -or mtfe \\r
268 -or mafe \\r
269 -or msfe \\r
270 -or mkfe \\r
271 -or msefe \\r
272 -a mrd \\r
273 -a mfr \\r
274 -a mtfe \\r
275 -a mafe \\r
276 -a msfe \\r
277 -a mkfe \\r
278 -a msefe evergreen_bre_import_file.bre > bibrecords.sql\r
279 ]]>\r
280 </userinput>\r
281 </screen>\r
282                         </step>\r
283                         <step>\r
284                                 <para>Load the records using psql and the sql scripts generated from the previous step.</para>\r
285 <screen>\r
286 <userinput>\r
287 <![CDATA[\r
288 psql -U evergreen -h localhost -d evergreen -f bibrecords.sql\r
289 psql -U evergreen < ~/Ever*/Open-ILS/src/extras/import/quick_metarecord_map.sql > log.create_metabib\r
290 ]]>\r
291 </userinput>\r
292 </screen>\r
293                         </step>\r
294                         <step>\r
295                                 <para>Extract holdings from marc records for importing copies into Evergreen using the <systemitem>extract_holdings</systemitem> utility.</para>\r
296 <screen>\r
297 <userinput>\r
298 extract_holdings --marcfile=clean.marc.xml --holding 999 --copyid 999i --map holdings.map\r
299 </userinput>\r
300 </screen>\r
301                                 <para>This command would extract holdings based on the 949 datafield in the marc records. The copy id is generated from the subfile i in the 999 datafield. You may \r
302                                 need to adjust these options based on the field used for holdings informatiom in your marc records.</para>\r
303                                 <para>The <option>map</option> option <filename>holdings.map</filename> refers to a file to be used for mapping subfields to the holdings data you would like extracted. Here is an example based on mapping holdings data to the 999 data field:</para>\r
304 <programlisting>\r
305 <![CDATA[\r
306 callnum 999 a\r
307 barcode 999 i\r
308 location 999 l\r
309 owning_lib 999 m\r
310 circ_modifier 999 t\r
311 ]]>\r
312 </programlisting>\r
313                                 <para>Running the extract holdings script should produce an sql script <filename>HOLDINGS.pg</filename> similar to:</para>\r
314 <programlisting language="sql">\r
315 BEGIN;\r
316 \r
317 egid, hseq, l_callnum, l_barcode, l_location, l_owning_lib, l_circ_modifier,\r
318 40      0       HD3616.K853 U54 1997    30731100751928  STACKS  FENNELL BOOK\r
319 41      1       HV6548.C3 S984 1998     30731100826613  STACKS  FENNELL BOOK\r
320 41      2       HV6548.C3 S984 1998     30731100804958  STACKS  BRANTFORD       BOOK\r
321 ...\r
322 </programlisting>\r
323   \r
324                                 <para>Edit the holdings.pg sql script like so:</para> \r
325 <programlisting language="sql">\r
326 BEGIN;\r
327 \r
328 <emphasis class="bold">TRUNCATE TABLE staging_items;</emphasis>\r
329 \r
330 <emphasis class="bold">INSERT INTO staging_items (</emphasis>egid, hseq, l_callnum, l_barcode, l_location, \r
331 l_owning_lib, l_circ_modifier) <emphasis>FROM stdin;</emphasis> \r
332 40      0       HD3616.K853 U54 1997    30731100751928  STACKS  FENNELL BOOK\r
333 41      1       HV6548.C3 S984 1998     30731100826613  STACKS  FENNELL BOOK\r
334 41      2       HV6548.C3 S984 1998     30731100804958  STACKS  BRANTFORD       BOOK\r
335 <emphasis>\.\r
336 \r
337 COMMIT;</emphasis>\r
338 </programlisting>\r
339                         <para>This file can be used for importing holdings into Evergreen. the <database class="field">egid</database> is a critical column. It is used to link the volume and \r
340                                 copy to the bibliographic record. Please refer to <link linkend="migratingbibrecordcopies">for the steps to import your holdings into Evergreen.</link></para> \r
341                         </step>\r
342                 </procedure>\r
343                 \r
344         </section>\r
345         <section xml:id="migratingbibrecordcopies">\r
346                 <title>Adding Copies to Bibliographic Records</title><indexterm><primary>migrating</primary><secondary>holdings</secondary></indexterm> \r
347                 <para>Before bibliographic records can be found in an OPAC search copies will need to be created.  It is very important to understand how various tables related to each other in regards \r
348                 to holdings maintenance.</para> \r
349                 <para>The following procedure will guide you through the process of populating Evergreen with volumes and copies. This is a very simple example. The SQL queries may need to be adjusted \r
350                 for the specific data in your holdings.</para>  \r
351                 <procedure>\r
352                         <step>\r
353                                 <para>Create a staging_items staging table to hold the holdings data:</para>\r
354 <programlisting language="sql">\r
355 CREATE TABLE staging_items (\r
356         l_callnum text, -- call number label\r
357         hseq int, \r
358         egid  int,  -- biblio.record_entry_id\r
359         createdate      date,\r
360         l_location        text,\r
361         l_barcode         text,\r
362         l_circ_modifier   text,\r
363         l_owning_lib      text  -- actor.org_unit.shortname\r
364 );\r
365 </programlisting>\r
366                         </step> \r
367                         <step>\r
368                                 <para>Import the items using the HOLDINGS.pg SQL script created using the extract_holdings utility.</para>\r
369 <screen>\r
370 <userinput>psql -U evergreen -f HOLDINGS.pg evergreen</userinput>\r
371 </screen>\r
372                                 <para>the file <filename>HOLDINGS.pg</filename> and/or the COPY query may need to be adjusted for your particular circumstances.</para>  \r
373                         </step>\r
374                         \r
375 \r
376                         <step>\r
377                                 <para>Generate shelving locations from your staging table.</para>\r
378 <programlisting language="sql">\r
379 INSERT INTO asset.copy_location (name, owning_lib)\r
380 SELECT  DISTINCT l.location, ou.id\r
381 FROM  staging_items l \r
382        JOIN actor.org_unit ou   ON (l.owning_lib = ou.shortname); \r
383 </programlisting>\r
384                         </step>\r
385                         <step>\r
386                                 <para>Generate circulation modifiers from your staging table.</para>\r
387 <programlisting language="sql">\r
388 INSERT INTO config.circ_modifier (code, name, description, sip2_media_type, magnetic_media)\r
389         SELECT  DISTINCT l_circ_modifier AS code,\r
390           l_circ_modifier AS name,\r
391           LOWER(l_circ_modifier) AS description,\r
392           '001' AS sip2_media_type,\r
393           FALSE AS magnetic_media\r
394           FROM  staging_items\r
395           WHERE l_circ_modifier NOT IN (SELECT code FROM config.circ_modifier);\r
396 </programlisting>\r
397                         </step>\r
398                         <step>\r
399                                 <para>Generate call numbers from your staging table:</para>\r
400 <programlisting language="sql">\r
401 INSERT INTO asset.call_number (creator,editor,record,label,owning_lib)\r
402 SELECT  DISTINCT 1, 1, egid, l.callnum, ou.id\r
403 FROM  staging.staging_items l\r
404 JOIN actor.org_unit ou ON (l.owning_lib = ou.shortname);\r
405 </programlisting>\r
406                         </step>\r
407                         <step>\r
408                                 <para>Generate copies from your staging table:</para>\r
409 <programlisting language="sql">\r
410 INSERT INTO asset.copy (\r
411 circ_lib, creator, editor, create_date, barcode,\r
412 STATUS, location, loan_duration, fine_level, circ_modifier, deposit, ref, call_number)          \r
413 \r
414 SELECT  DISTINCT ou.id AS circ_lib,\r
415         1 AS creator,\r
416         1 AS editor,\r
417         l.l_createdate AS create_date,\r
418         l.l_barcode AS barcode,\r
419         0 AS STATUS,\r
420         cl.id AS location,\r
421         2 AS loan_duration,\r
422         2 AS fine_level,\r
423         l.l_circ_modifier AS circ_modifier,\r
424         FALSE AS deposit,\r
425         CASE\r
426         WHEN l.l_circ_modifier = 'REFERENCE' THEN TRUE\r
427         ELSE FALSE\r
428         END AS ref,                                             \r
429         cn.id AS call_number\r
430         FROM  staging_items l\r
431                 JOIN actor.org_unit ou\r
432                         ON (l.l_owning_lib = ou.shortname)\r
433                 JOIN asset.copy_location cl\r
434                         ON (ou.id = cl.owning_lib AND l.l_location = cl.name)\r
435                 JOIN metabib.real_full_rec m \r
436                         ON (m.record = l.egid)\r
437                 JOIN asset.call_number cn\r
438                         ON (ou.id = cn.owning_lib  \r
439                         AND m.record = cn.record       \r
440                         AND l.l_callnum = cn.label)      \r
441 </programlisting>\r
442                                 <para>You should now have copies in your Evergreen database and should be able to search and find the bibliographic records with attached copies.</para> \r
443                         </step>\r
444                 </procedure>\r
445         </section>\r
446         <section xml:id="migratingpatrons">\r
447                 <title>Migrating Patron Data</title>\r
448                 <indexterm><primary>migrating</primary><secondary>patrons</secondary></indexterm>\r
449                 <para>\r
450                 This section will explain the task of migrating your patron data from comma delimited files<indexterm><primary>comma delimited files</primary></indexterm> into Evergreen. \r
451                 It does not deal with the process of exporting from the non-Evergreen \r
452                 system since this process may vary depending on where you are extracting your patron records. Patron could come from an ILS or it could come from a student database in the case of \r
453                 academic records.               \r
454                 </para>\r
455                 <para>When importing records into Evergreen you will need to populate 3 tables in your Evergreen database:</para>\r
456                 <itemizedlist>\r
457                         <listitem><link linkend="actor.table.usr">actor.usr</link> - The main table for user data</listitem>\r
458                         <listitem><link linkend="actor.table.card">actor.card</link> - Stores the barcode for users; Users can have more than 1 card but only 1 can be active at a given time;</listitem>\r
459                         <listitem><link linkend="actor.table.usr-address">actor.usr_address</link> - Used for storing address information; A user can have more than one address.</listitem>\r
460                 </itemizedlist>\r
461                 <para>Before following the procedures below to import patron data into Evergreen, it is a good idea to examine the fields in these tables in order to decide on a strategy \r
462                 for data to include \r
463                 in your import. It is important to understand the data types and constraints on each field.</para>\r
464                 <procedure>\r
465                         <step>\r
466                                 <para>Export the patron data from your existing ILS or from another source into a comma delimited file. The comma delimited file used for importing\r
467                                  the records should use Unicode (UTF8) <indexterm><primary>Unicode</primary></indexterm> character encoding.</para>\r
468                         </step>\r
469                         <step>\r
470                                 <para>Create a staging table.<indexterm><primary>staging table</primary></indexterm>  A staging table will allow you to tweak the data before importing. \r
471                                 Here is an example sql statement:</para>\r
472 <indexterm><primary>sql</primary></indexterm> \r
473 <programlisting language="sql">\r
474 CREATE TABLE students (\r
475          student_id int, barcode text, last_name text, first_name text, email text, address_type text, street1 text, street2 text, \r
476         city text, province text, country text, postal_code text, phone text, profile int DEFAULT 2, \r
477         ident_type int, home_ou int, claims_returned_count int DEFAULT 0, usrname text, \r
478         net_access_level int DEFAULT 2, password text\r
479 ); \r
480 </programlisting>\r
481                                 <para>Note the <varname>DEFAULT</varname> variables. These allow you to set default for your library or to populate required fields if you \r
482                                 data allows <systemitem>NULL</systemitem> values where fields are required in Evergreen.</para>\r
483                                 <para>The data field <database class="field">profile</database> in the above SQL script refers to the user group and should be an\r
484                                 integer referencing the <database class="field">id</database> field in <link linkend="permission.table.grp-tree">\r
485                                 <database class="table">permission.grp_tree</database></link>. \r
486                                 Setting this value will effect the permissions for the user. See the values in <database class="table">permission.grp_tree</database> for \r
487                                 possibilities.</para> \r
488                                 <para> <database class="field">ident_type</database> is the identification type used for identiying users. This is a integer value referencing \r
489                                 <database class="table">config.identification_type</database> and should match the id values of that table. The default values are \r
490                                 <literal>1</literal> for Drivers License, <literal>2</literal> for SSN or <literal>3</literal> for other.</para>\r
491                                 <para><database class="field">home_ou</database> is the home organizational unit for the user. This value needs to match the corresponding \r
492                                 <database class="field">id</database> in the <link linkend="actor.table.org-unit"><database class="table">actor.org_unit</database></link> \r
493                                 table.</para>    \r
494                         </step>\r
495                         <step>\r
496                                 <para>Copy records into staging table from a comma delimited file.</para>\r
497 <programlisting language="sql">\r
498 COPY students (student_id, last_name, first_name, email, address_type, street1, street2, city, province, country, postal_code, phone) \r
499         FROM '/home/opensrf/patrons.csv' \r
500                 WITH CSV HEADER;  \r
501 </programlisting>\r
502                                 <para>The above script wil vary depending on the format of your patron load file (<filename>patrons.csv</filename>). You may want to review \r
503                                 <link xl:href="http://www.postgresql.org/docs/9.0/static/sql-copy.html" xl:title="PostgreSQL - COPY">PostgreSQL documentation</link></para>  \r
504                         </step>\r
505                         <step>\r
506                                 <para>Formatting of some fields to fit Evergreen filed formatting may be required. Here is an example of sql to adjust phone numbers in the staging \r
507                                 table to fit the evergreen field:</para>\r
508 <programlisting language="sql">\r
509 UPDATE students phone = replace(replace(replace(rpad(substring(phone from 1 for 9), 10, '-') || \r
510 substring(phone from 10), '(', ''), ')', ''), ' ', '-');\r
511 </programlisting>\r
512                                 <para>Data <quote>massaging</quote> will be required to fit formats used in Evergreen.</para>\r
513                         </step>\r
514                         <step>\r
515                                 <para>Insert records from the staging table into the <link linkend="actor.table.usr"><database class="table">actor.usr</database> </link> Evergreen table:</para>\r
516 <programlisting language="sql">\r
517  INSERT INTO actor.usr (\r
518         profile, usrname, email, passwd, ident_type, ident_value, first_given_name, \r
519         family_name, day_phone, home_ou, claims_returned_count, net_access_level) \r
520         SELECT profile, students.usrname, email, password, ident_type, student_id, \r
521         first_name, last_name, phone, home_ou, claims_returned_count, net_access_level \r
522         FROM students;\r
523 </programlisting>               \r
524                         </step>\r
525                         <step>\r
526                                 <para>insert records into <link linkend="actor.table.card"><database class="table">actor.card </database></link> from <link linkend="actor.table.usr">\r
527                                 <database class="table">actor.usr </database></link>.</para>\r
528 <programlisting language="sql">\r
529 INSERT INTO actor.card (usr, barcode) \r
530         SELECT actor.usr.id, students.barcode \r
531         FROM students \r
532                 INNER JOIN actor.usr \r
533                         ON students.usrname = actor.usr.usrname;\r
534 </programlisting>               \r
535                                 <para>This assumes a one to one card patron relationship. If your patron data import has multiple cards assigned to one patron more complex import scripts may be required                                      which look for inactive or active flags.</para> \r
536                         </step>\r
537                         <step>\r
538                                 <para>Update actor.usr.card field with actor.card.id to associate active card with the user:</para>\r
539 <programlisting language="sql">\r
540 UPDATE actor.usr \r
541         SET card = actor.card.id \r
542         FROM actor.card \r
543         WHERE actor.card.usr = actor.usr.id;\r
544 </programlisting>                       \r
545                         </step>\r
546                         <step>\r
547                                 <para>Insert records into <link linkend="actor.table.usr-address">actor.usr_address</link> to add address information for users:</para>\r
548 <programlisting language="sql">\r
549 INSERT INTO actor.usr_address (usr, street1, street2, city, state, country, post_code) \r
550         SELECT actor.usr.id, students.street1, students.street2, students.city, students.province, \r
551         students.country, students.postal_code \r
552         FROM students \r
553         INNER JOIN actor.usr ON students.usrname = actor.usr.usrname;\r
554 </programlisting>                       \r
555                         </step>\r
556                         <step>\r
557                                 <para>update <link linkend="actor.table.usr-address">actor.usr.address</link> with address id from address table.</para>\r
558 <programlisting language="sql">\r
559 UPDATE actor.usr \r
560         SET mailing_address = actor.usr_address.id, billing_address = actor.usr_address.id \r
561         FROM actor.usr_address \r
562         WHERE actor.usr.id = actor.usr_address.usr;\r
563 </programlisting>       \r
564                         <para>This assumes 1 address per patron. More complex scenarios may require more sophisticated SQL.</para>              \r
565                         </step>\r
566                 </procedure>\r
567                 <simplesect>\r
568                         <title>Creating an sql Script for Importing Patrons</title>\r
569                         <para>The procedure for importing patron can be automated with the help of an sql script. Follow these steps to create an import script:</para>\r
570                 \r
571                         <procedure>\r
572                                 <step>\r
573                                         <para>Create an new file and name it <filename>import.sql</filename></para>\r
574 \r
575                                 </step>\r
576 \r
577                                 <step>\r
578                                         <para>Edit the file to look similar to this:</para>\r
579 <programlisting>\r
580 BEGIN;\r
581 \r
582 -- Create staging table.\r
583 CREATE TABLE students (\r
584         student_id int, barcode text, last_name text, first_name text, email text, address_type text, street1 text, street2 text, \r
585         city text, province text, country text, postal_code text, phone text, profile int, \r
586         ident_type int, home_ou int, claims_returned_count int DEFAULT 0, usrname text, \r
587         net_access_level int DEFAULT 2, password text\r
588 ); \r
589 \r
590 --Copy records from your import text file\r
591 COPY students (student_id, last_name, first_name, email, address_type, street1, street2, city, province, country, postal_code, phone, password) \r
592         FROM '/home/opensrf/patrons.csv' \r
593                 WITH CSV HEADER;  \r
594 \r
595 \r
596 --Insert records from the staging table into the actor.usr table.\r
597 INSERT INTO actor.usr (\r
598         profile, usrname, email, passwd, ident_type, ident_value, first_given_name, family_name, \r
599         day_phone, home_ou, claims_returned_count, net_access_level) \r
600         SELECT profile, students.usrname, email, password, ident_type, student_id, first_name, \r
601         last_name, phone, home_ou, claims_returned_count, net_access_level FROM students;\r
602 \r
603 --Insert records from the staging table into the actor.usr table.\r
604 INSERT INTO actor.card (usr, barcode) \r
605         SELECT actor.usr.id, students.barcode \r
606         FROM students \r
607                 INNER JOIN actor.usr \r
608                         ON students.usrname = actor.usr.usrname;\r
609 \r
610 --Update actor.usr.card field with actor.card.id to associate active card with the user:\r
611 UPDATE actor.usr \r
612         SET card = actor.card.id \r
613         FROM actor.card \r
614         WHERE actor.card.usr = actor.usr.id;\r
615 \r
616 --INSERT records INTO actor.usr_address from staging table.\r
617 INSERT INTO actor.usr_address (usr, street1, street2, city, state, country, post_code) \r
618         SELECT actor.usr.id, students.street1, students.street2, students.city, students.province, \r
619         students.country, students.postal_code \r
620         FROM students \r
621         INNER JOIN actor.usr ON students.usrname = actor.usr.usrname;\r
622 \r
623 \r
624 --Update actor.usr mailing address with id from actor.usr_address table.:\r
625 UPDATE actor.usr \r
626         SET mailing_address = actor.usr_address.id, billing_address = actor.usr_address.id \r
627         FROM actor.usr_address \r
628         WHERE actor.usr.id = actor.usr_address.usr;\r
629 \r
630 COMMIT;\r
631 </programlisting>\r
632                                         <para>Placing the sql statements between <code>BEGIN;</code> and <code>COMMIT;</code> creates a transaction block so that if any sql statements fail, the \r
633                                         entire process is canceled and the database is rolled back to its original state. Lines beginning with <code>--</code> are comments to let you you what \r
634                                         each sql statement is doing and are not processed.</para> \r
635                                 </step>\r
636                         </procedure>\r
637                 </simplesect>\r
638                 <simplesect>\r
639                         <title>Batch Updating Patron Data</title>\r
640                         <indexterm><primary>migrating</primary><secondary>batch updating patrons</secondary></indexterm>\r
641                         <para>For academic libraries, doing batch updates to add new patrons to the Evergreen database is a critical task. The above procedures and \r
642                         import script can be easily adapted to create an update script for importing new patrons from external databases. If the data import file contains only new patrons, then, \r
643                         the above procedures will work well to insert those patrons. However, if the data load contains all patrons, a second staging table and a procedure to remove existing                          patrons from that second staging table may be required before importing the new patrons. Moreover, additional steps to update address information and perhaps delete \r
644                         inactive patrons may also be desired depending on the requirements of the institution.</para>\r
645                         <para>After developing the scripts to import and update patrons have been created, another important task for library staff is to develop an import strategy and schedule \r
646                         which suits the needs of the library. This could be determined by registration dates of your institution in the case of academic libraries. It is important to balance \r
647                         the convenience of patron loads and the cost of processing these loads vs staff adding patrons manually.</para>   \r
648                </simplesect> \r
649         </section>\r
650         <section xml:id="emptydatabase">\r
651                 <title>Restoring your Evergreen Database to an Empty State</title>\r
652                 <para>If you've done a test import of records and you want to quickly get Evergreen back to a pristine state, you can create a clean Evergreen database schema by performing the \r
653                 following:</para>\r
654                 <procedure>\r
655                         <step> \r
656 <screen>\r
657 <userinput>cd ILS/Open-ILS/src/sql/Pg/</userinput>\r
658 </screen>\r
659                         </step>\r
660                          <step> \r
661                                  <para>Rebuild the database schema:</para>\r
662 <screen>\r
663 <userinput>./build-db.sh [db-hostname> [db-port] [db-name] [db-user] [db-password] [db-version]</userinput>\r
664 </screen>\r
665                                 <caution><para>This will remove all of your data from the database and restore the default values.</para></caution>             \r
666                         </step>\r
667                 </procedure>\r
668         </section>\r
669         <section xml:id="exportingbibrecordsintoMARC">\r
670                 <title>Exporting Bibliographic Records into MARC files</title>\r
671                 <indexterm><primary>migrating</primary><secondary>exporting bibliographic records</secondary><tertiary>MARC</tertiary></indexterm>\r
672                 <para>The following procedure explains how to export Evergreen bibliographic records into MARC files using the marc_export support script. All steps should be performed by the \r
673                 opensrf user from your Evergreen server.</para>\r
674                 <procedure>\r
675                         <step> \r
676                                 <para>Create a text file list of the Bibliographic record ids you would like to export from Evergreen. One way to do this is using SQL:</para>\r
677 <programlisting language="sql">\r
678 SELECT DISTINCT bre.id FROM biblio.record_entry AS bre\r
679         JOIN asset.call_number AS acn ON acn.record-bre.id \r
680         WHERE bre.deleted='false' and ownling_lib=101 \g /home/opensrf/records.txt;\r
681 </programlisting>\r
682                                 <para>This query will create a file called <filename>records.txt</filename> containing a column of distinct ids of items owned by the organizational unit with the \r
683                                 <database class="field">id</database> <literal>101</literal>.</para>\r
684                         </step>\r
685                         <step>\r
686                                 <para>Navigate to the support-scripts folder</para>\r
687 <screen>\r
688 <userinput>cd /home/opensrf/Evergreen-ILS*/Open-ILS/src/support-scripts/</userinput>\r
689 </screen>\r
690                         </step>\r
691                         <step>\r
692                                 <para>Run <command>marc_export</command>, using the id file you created in step 1 to define which files to export.</para>\r
693 <screen>\r
694 <userinput>cat /home/opensrf/records.txt | ./marc_export -i -c /openils/conf/opensrf_core.xml \\r
695 -x /openils/conf/fm_IDL.xml -f XML --timeout 5 > exported_files.xml\r
696 </userinput>\r
697 </screen>\r
698                                 <para>The example above export the records into MARCXML format.</para>\r
699                                 <note>\r
700                                 <para>For help or for more options when running <command>marc_export</command>, run <command>marc_export</command> with the <option>-h</option> option:</para>\r
701 <screen>\r
702 <userinput>./marc_export -h</userinput>\r
703 </screen>\r
704                                 </note>\r
705                                 \r
706                         </step>\r
707                                 <note>\r
708                                 <para>Processing time for exporting records will depond on several factors such as the number of records you are exporting. It is recommended that you divide the \r
709                                 export id files (<filename>records.txt</filename>) into manageable number of records if you are exporting a large number of records.</para> \r
710                                 </note>\r
711                 </procedure>\r
712         </section>      \r
713         <section xml:id="importingauthorityrecords">\r
714                 <title>Importing Authority Records</title>\r
715                 <indexterm><primary>migrating</primary><secondary>importing authority records</secondary></indexterm>\r
716                 <para>The following procedure explains how to export Evergreen bibliographic records into MARC files using the marc_export support script. All steps should be performed by the \r
717                 opensrf user from your Evergreen server.</para>\r
718                 <simplesect>\r
719                         <title>Importing Authority Records from Command Line</title>\r
720                         <para>The major advantages of the command line approach are its speed and its convenience for system administrators who can perform bulk loads of authority records in a \r
721                         controlled environment.</para>          \r
722                         <procedure>\r
723 \r
724                                 <step> \r
725                                         <para>Run <command>marc2are.pl</command> against the authority records, specifying the user name, password, MARC type (USMARC or XML). Use \r
726                                         <varname>STDOUT</varname> redirection \r
727                                         to either pipe the output directly into the next command or into an output file for inspection. For example, to process a set of authority records \r
728                                         named <filename>auth_small.xml</filename> using the default user name and password and directing the output into a file named <filename>auth.are</filename>:</para>\r
729 <screen>\r
730 <userinput>cd Open-ILS/src/extras/import/</userinput>\r
731 <userinput>perl marc2are.pl --user admin --pass open-ils auth_small.xml > auth.are</userinput>\r
732 </screen>\r
733                                 \r
734                                 </step>\r
735                                 <step> \r
736                                         <para>Run <command>pg_loader.pl</command> to generate the SQL necessary for importing the authority records into your system. To save time for very large batches of records, you could \r
737                                         simply pipe the output of <command>marc2are.pl</command> directly into <command>pg_loader.pl</command>.</para>\r
738 <screen>\r
739 <userinput>cd Open-ILS/src/extras/import/</userinput>\r
740 <userinput> perl pg_loader.pl --auto are --order are auth.are > auth_load.sql</userinput>\r
741 </screen>\r
742                                 \r
743                                 </step>\r
744                                 <step> \r
745                                         <para>Load the authority records from the SQL file that you generated in the last step into your Evergreen database using the psql tool. Assuming the default user \r
746                                         name, host name, and database name for an Evergreen instance, that command looks like:</para>\r
747 <screen>\r
748 <userinput>psql -U evergreen -h localhost -d evergreen -f auth_load.sql</userinput>\r
749 </screen>\r
750                                 \r
751                                 </step>\r
752                         </procedure>\r
753                 </simplesect>\r
754                 <simplesect>\r
755                         <title>Importing authority records using the MARC Batch Import/Export interface from the Staff Client</title>\r
756                         <para>Good for loading batches of up to 5,000 records (roughly) at a time, the major advantages to importing authority records using the MARC Batch Import/Export interface are \r
757                         that it does not require command-line or direct database access – good for both security in that it minimizes the number of people who need this access and for spreading the \r
758                         effort around to others in the library – and it does most of the work (for example, figuring out whether the batch of records is in XML or USMARC format) for you.</para> \r
759                         <para>To import a set of MARC authority records from the MARC Batch Import/Export interface:</para>\r
760                         <procedure>\r
761                                 <step> \r
762                                         <para>From the Evergreen staff client, select <menuchoice><guimenu>Cataloging</guimenu><guimenuitem>MARC Batch Import/Export</guimenuitem></menuchoice>. \r
763                                         The <guilabel>Evergreen MARC File Upload</guilabel> screen opens, with <guilabel>Import Records</guilabel> as the highlighted tab.</para>\r
764                                 </step>\r
765                                 <step> \r
766                                         <para>From the <guimenu>Bibliographic records</guimenu> drop-down menu, select <guimenuitem>Authority records</guimenuitem>.</para>\r
767                                 \r
768                                 </step>\r
769                                 <step> \r
770                                         <para>Enter a name for the queue (batch import job) in the <guilabel>Create a new upload queue</guilabel> field.</para>\r
771                                 \r
772                                 </step>\r
773                                 <step> \r
774                                         <para>Select the <guilabel>Auto-Import Non-Colliding Records</guilabel> checkbox.</para>\r
775                                 \r
776                                 </step>\r
777                                 <step> \r
778                                         <para>Click the <guibutton>Browse…</guibutton> button to select the file of MARC authorities to import.</para>\r
779                                 \r
780                                 </step>\r
781                                 <step> \r
782                                         <para>Click the <guibutton>Upload</guibutton> button to begin importing the records. The screen displays <guilabel>Uploading…</guilabel>\r
783                                         <guilabel>Processing…</guilabel> to show that the records are being transferred to the server, then displays a progress bar to show the actual import \r
784                                         progress. When the staff client displays the progress bar, you can disconnect your staff client safely. Very large batches of records might time out at this \r
785                                         stage.</para>\r
786                                 \r
787                                 </step>\r
788                                 <step> \r
789                                         <para>Once the import is finished, the staff client displays the results of the import process. You can manually display the import progress by selecting \r
790                                         the <guilabel>Inspect Queue</guilabel> tab of the MARC Batch Import/Export interface and selecting the queue name. By default, the staff client does not \r
791                                         display records that were imported successfully; it only shows records that conflicted with existing entries in the database. The screen shows the overall \r
792                                         status of the import process in the top right-hand corner, with the <guilabel>Total</guilabel> and <guilabel>Imported</guilabel> number of records for the \r
793                                         queue.</para>\r
794                                 </step>\r
795                         </procedure>\r
796 \r
797                 </simplesect>\r
798 \r
799         </section>\r
800 </chapter>\r
801    \r
802       \r
803 \r
804 \r
805  \r
806 \r
807 \r