traject 2.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +27 -0
- data/.yardopts +3 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +20 -0
- data/README.md +461 -0
- data/Rakefile +21 -0
- data/bench/bench.rb +30 -0
- data/bin/traject +16 -0
- data/doc/batch_execution.md +243 -0
- data/doc/extending.md +190 -0
- data/doc/indexing_rules.md +265 -0
- data/doc/other_commands.md +47 -0
- data/doc/settings.md +101 -0
- data/lib/tasks/load_maps.rake +48 -0
- data/lib/traject.rb +11 -0
- data/lib/traject/command_line.rb +301 -0
- data/lib/traject/csv_writer.rb +34 -0
- data/lib/traject/debug_writer.rb +47 -0
- data/lib/traject/delimited_writer.rb +110 -0
- data/lib/traject/indexer.rb +613 -0
- data/lib/traject/indexer/settings.rb +110 -0
- data/lib/traject/json_writer.rb +51 -0
- data/lib/traject/line_writer.rb +63 -0
- data/lib/traject/macros/basic.rb +9 -0
- data/lib/traject/macros/marc21.rb +223 -0
- data/lib/traject/macros/marc21_semantics.rb +584 -0
- data/lib/traject/macros/marc_format_classifier.rb +197 -0
- data/lib/traject/marc_extractor.rb +410 -0
- data/lib/traject/marc_reader.rb +89 -0
- data/lib/traject/mock_reader.rb +97 -0
- data/lib/traject/ndj_reader.rb +40 -0
- data/lib/traject/null_writer.rb +22 -0
- data/lib/traject/qualified_const_get.rb +40 -0
- data/lib/traject/solr_json_writer.rb +277 -0
- data/lib/traject/thread_pool.rb +161 -0
- data/lib/traject/translation_map.rb +267 -0
- data/lib/traject/util.rb +52 -0
- data/lib/traject/version.rb +3 -0
- data/lib/traject/yaml_writer.rb +9 -0
- data/lib/translation_maps/lcc_top_level.yaml +26 -0
- data/lib/translation_maps/marc_genre_007.yaml +9 -0
- data/lib/translation_maps/marc_genre_leader.yaml +22 -0
- data/lib/translation_maps/marc_geographic.yaml +589 -0
- data/lib/translation_maps/marc_instruments.yaml +102 -0
- data/lib/translation_maps/marc_languages.yaml +490 -0
- data/test/debug_writer_test.rb +38 -0
- data/test/delimited_writer_test.rb +104 -0
- data/test/indexer/each_record_test.rb +59 -0
- data/test/indexer/macros_marc21_semantics_test.rb +391 -0
- data/test/indexer/macros_marc21_test.rb +190 -0
- data/test/indexer/macros_test.rb +40 -0
- data/test/indexer/map_record_test.rb +209 -0
- data/test/indexer/read_write_test.rb +101 -0
- data/test/indexer/settings_test.rb +152 -0
- data/test/indexer/to_field_test.rb +77 -0
- data/test/marc_extractor_test.rb +412 -0
- data/test/marc_format_classifier_test.rb +98 -0
- data/test/marc_reader_test.rb +110 -0
- data/test/solr_json_writer_test.rb +248 -0
- data/test/test_helper.rb +90 -0
- data/test/test_support/245_no_ab.marc +1 -0
- data/test/test_support/880_with_no_6.utf8.marc +1 -0
- data/test/test_support/bad_subfield_code.marc +1 -0
- data/test/test_support/bad_utf_byte.utf8.marc +1 -0
- data/test/test_support/date_resort_to_260.marc +1 -0
- data/test/test_support/date_type_r_missing_date2.marc +1 -0
- data/test/test_support/date_with_u.marc +1 -0
- data/test/test_support/demo_config.rb +155 -0
- data/test/test_support/emptyish_record.marc +1 -0
- data/test/test_support/escaped_character_reference.marc8.marc +1 -0
- data/test/test_support/george_eliot.marc +1 -0
- data/test/test_support/hebrew880s.marc +1 -0
- data/test/test_support/louis_armstrong.marc +1 -0
- data/test/test_support/manufacturing_consent.marc +1 -0
- data/test/test_support/manuscript_online_thesis.marc +1 -0
- data/test/test_support/microform_online_conference.marc +1 -0
- data/test/test_support/multi_era.marc +1 -0
- data/test/test_support/multi_geo.marc +1 -0
- data/test/test_support/musical_cage.marc +1 -0
- data/test/test_support/nature.marc +1 -0
- data/test/test_support/one-marc8.mrc +1 -0
- data/test/test_support/online_only.marc +1 -0
- data/test/test_support/packed_041a_lang.marc +1 -0
- data/test/test_support/test_data.utf8.json +30 -0
- data/test/test_support/test_data.utf8.marc.xml +2609 -0
- data/test/test_support/test_data.utf8.mrc +1 -0
- data/test/test_support/test_data.utf8.mrc.gz +0 -0
- data/test/test_support/the_business_ren.marc +1 -0
- data/test/translation_map_test.rb +225 -0
- data/test/translation_maps/bad_ruby.rb +8 -0
- data/test/translation_maps/bad_yaml.yaml +1 -0
- data/test/translation_maps/both_map.rb +1 -0
- data/test/translation_maps/both_map.yaml +1 -0
- data/test/translation_maps/default_literal.rb +10 -0
- data/test/translation_maps/default_passthrough.rb +10 -0
- data/test/translation_maps/marc_040a_translate_test.yaml +1 -0
- data/test/translation_maps/properties_map.properties +5 -0
- data/test/translation_maps/ruby_map.rb +10 -0
- data/test/translation_maps/translate_array_test.yaml +8 -0
- data/test/translation_maps/yaml_map.yaml +7 -0
- data/traject.gemspec +47 -0
- metadata +382 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'marc'
|
|
2
|
+
require 'traject/ndj_reader'
|
|
3
|
+
|
|
4
|
+
# `Traject::MarcReader` uses pure ruby marc gem to parse MARC records. It
|
|
5
|
+
# can read MARC ISO 2709 ('binary'), MARC-XML, and Marc-in-json (newline-delimited-json).
|
|
6
|
+
#
|
|
7
|
+
# Marc4JReader is an alternative to this class, powered by Marc4J. You may be interested
|
|
8
|
+
# in comparing for performance, under your particular use case. To use it, you'll need
|
|
9
|
+
# the gem traject-marc4j_reader.
|
|
10
|
+
#
|
|
11
|
+
# By default assumes binary MARC encoding, please set marc_source.type setting
|
|
12
|
+
# for XML or json. If binary, please set marc_source.encoding with char encoding.
|
|
13
|
+
#
|
|
14
|
+
# ## Settings
|
|
15
|
+
|
|
16
|
+
# * "marc_source.type": serialization type. default 'binary'
|
|
17
|
+
# * "binary". standard ISO 2709 "binary" MARC format,
|
|
18
|
+
# will use ruby-marc MARC::Reader (Note, if you are using
|
|
19
|
+
# type 'binary', you probably want to also set 'marc_source.encoding')
|
|
20
|
+
# * "xml", MarcXML, will use ruby-marc MARC::XMLReader
|
|
21
|
+
# * "json" The "marc-in-json" format, encoded as newline-separated
|
|
22
|
+
# json. (synonym 'ndj'). A simplistic newline-separated json, with no comments
|
|
23
|
+
# allowed, and no unescpaed internal newlines allowed in the json
|
|
24
|
+
# objects -- we just read line by line, and assume each line is a
|
|
25
|
+
# marc-in-json. http://dilettantes.code4lib.org/blog/2010/09/a-proposal-to-serialize-marc-in-json/
|
|
26
|
+
# will use Traject::NDJReader which uses MARC::Record.new_from_hash.
|
|
27
|
+
# * "marc_source.encoding": Only used for marc_source.type 'binary', character encoding
|
|
28
|
+
# of the source marc records. Can be any
|
|
29
|
+
# encoding recognized by ruby, OR 'MARC-8'. For 'MARC-8', content will
|
|
30
|
+
# be transcoded (by ruby-marc) to UTF-8 in internal MARC::Record Strings.
|
|
31
|
+
# Default nil, meaning let MARC::Reader use it's default, which will
|
|
32
|
+
# probably be Encoding.default_internal, which will probably be UTF-8.
|
|
33
|
+
# Right now Traject::MarcReader is hard-coded to transcode to UTF-8 as
|
|
34
|
+
# an internal encoding.
|
|
35
|
+
# * "marc_reader.xml_parser": For XML type, which XML parser to tell Marc::Reader
|
|
36
|
+
# to use. Anything recognized by [Marc::Reader :parser
|
|
37
|
+
# argument](http://rdoc.info/github/ruby-marc/ruby-marc/MARC/XMLReader).
|
|
38
|
+
# By default, asks Marc::Reader to take
|
|
39
|
+
# it's best guess as to highest performance available
|
|
40
|
+
# installed option. Probably best to leave as default.
|
|
41
|
+
#
|
|
42
|
+
# ## Example
|
|
43
|
+
#
|
|
44
|
+
# In a configuration file:
|
|
45
|
+
#
|
|
46
|
+
# require 'traject/marc_reader'
|
|
47
|
+
#
|
|
48
|
+
# settings do
|
|
49
|
+
# provide "reader_class_name", "Traject::MarcReader"
|
|
50
|
+
# provide "marc_source.type", "xml"
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
class Traject::MarcReader
|
|
54
|
+
include Enumerable
|
|
55
|
+
|
|
56
|
+
attr_reader :settings, :input_stream
|
|
57
|
+
|
|
58
|
+
@@best_xml_parser = MARC::XMLReader.best_available
|
|
59
|
+
|
|
60
|
+
def initialize(input_stream, settings)
|
|
61
|
+
@settings = Traject::Indexer::Settings.new settings
|
|
62
|
+
@input_stream = input_stream
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Creates proper kind of ruby MARC reader, depending
|
|
66
|
+
# on settings or guesses.
|
|
67
|
+
def internal_reader
|
|
68
|
+
unless defined? @internal_reader
|
|
69
|
+
@internal_reader =
|
|
70
|
+
case settings["marc_source.type"]
|
|
71
|
+
when "xml"
|
|
72
|
+
parser = settings["marc_reader.xml_parser"] || @@best_xml_parser
|
|
73
|
+
MARC::XMLReader.new(self.input_stream, :parser=> parser)
|
|
74
|
+
when 'json'
|
|
75
|
+
Traject::NDJReader.new(self.input_stream, settings)
|
|
76
|
+
else
|
|
77
|
+
args = { :invalid => :replace }
|
|
78
|
+
args[:external_encoding] = settings["marc_source.encoding"]
|
|
79
|
+
MARC::Reader.new(self.input_stream, args)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
return @internal_reader
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def each(*args, &block)
|
|
86
|
+
self.internal_reader.each(*args, &block)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Encoding: utf-8
|
|
2
|
+
require 'marc'
|
|
3
|
+
require 'json'
|
|
4
|
+
module Traject
|
|
5
|
+
|
|
6
|
+
# A mock reader, designed to do almost no work during a run to provide better benchmarking
|
|
7
|
+
#
|
|
8
|
+
# It pulls in 20 records from the end of this file and then just returns
|
|
9
|
+
# them over and over again, up to the specified limit
|
|
10
|
+
#
|
|
11
|
+
# Specify in a config files as follows:
|
|
12
|
+
#
|
|
13
|
+
# require 'traject/mock_writer'
|
|
14
|
+
# require 'traject/mock_reader'
|
|
15
|
+
#
|
|
16
|
+
# settings do
|
|
17
|
+
# store "reader_class_name", "Traject::MockReader"
|
|
18
|
+
# store "writer_class_name", "Traject::MockWriter"
|
|
19
|
+
# store "mock_reader.limit", 4_000 # default is 10_000
|
|
20
|
+
# end
|
|
21
|
+
class MockReader
|
|
22
|
+
|
|
23
|
+
attr_accessor :limit
|
|
24
|
+
|
|
25
|
+
# @param [Ignored] input_stream (ignored)
|
|
26
|
+
# @param [Hash] settings (looks only for an integer in 'mock_reader.limit')
|
|
27
|
+
def initialize(input_stream, settings = {})
|
|
28
|
+
@limit = (settings["mock_reader.limit"] || 10_000).to_i
|
|
29
|
+
|
|
30
|
+
@records = load_ndjson(File.open(__FILE__))
|
|
31
|
+
|
|
32
|
+
# freeze it immutable for thread safety and performance
|
|
33
|
+
@records.each {|r| r.fields.freeze}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# newline delimited json, assuming no internal unescaped
|
|
37
|
+
# newlines in json too!
|
|
38
|
+
def load_ndjson(file_io)
|
|
39
|
+
records = []
|
|
40
|
+
|
|
41
|
+
this_file_iter = file_io.each_line
|
|
42
|
+
|
|
43
|
+
while true
|
|
44
|
+
line = this_file_iter.next
|
|
45
|
+
break if line =~ /^\_\_END\_\_/
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
begin
|
|
49
|
+
while true
|
|
50
|
+
json = this_file_iter.next
|
|
51
|
+
next unless json =~ /\S/
|
|
52
|
+
records << MARC::Record.new_from_hash(JSON.parse(json))
|
|
53
|
+
end
|
|
54
|
+
rescue StopIteration
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
return records
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def each
|
|
62
|
+
unless block_given?
|
|
63
|
+
enum_for(:each)
|
|
64
|
+
else
|
|
65
|
+
size = @records.size
|
|
66
|
+
@limit.times do |i|
|
|
67
|
+
yield @records[i % size]
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
__END__
|
|
77
|
+
{"leader":"01195nam a22004331 4500","fields":[{"001":"000001580"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1970 enk |00100 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"74120936"}]}},{"015":{"ind1":" ","ind2":" ","subfields":[{"a":"B70-19354"}]}},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"0631126902"},{"c":"45/-"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0113131-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159819858"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00113131"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-wu1874523"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"043":{"ind1":" ","ind2":" ","subfields":[{"a":"e-uk---"}]}},{"050":{"ind1":" ","ind2":"4","subfields":[{"a":"HD1491.G7"},{"b":"D521 1970"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"334/.683/0917242"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Digby, Margaret,"},{"d":"1902-"}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Agricultural co-operation in the Commonwealth."}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"2nd ed."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Oxford,"},{"b":"Blackwell,"},{"c":"1970."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"[1], vii, 222 p."},{"c":"23 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Agriculture, Cooperative"},{"z":"Great Britain"},{"x":"Colonies."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"BUHR"},{"c":"GRAD"},{"h":"HD1491.G7 D521 1970"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"a":"wu"},{"b":"SDR"},{"c":"WU"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015030215993"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"wu.89041950478"},{"r":"ic"},{"d":"20120529"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
78
|
+
{"leader":"01444nam a22004571 4500","fields":[{"001":"000001646"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1969 onc b 00110 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"75520445"}]}},{"015":{"ind1":" ","ind2":" ","subfields":[{"a":"C***"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0117360-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159819933"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00117360"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-nrlf-ucscb16742595x"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"041":{"ind1":"1","ind2":" ","subfields":[{"a":"eng"},{"h":"lat"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"PA8395.P36"},{"b":"D513"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"398.2/0917/4927"}]}},{"100":{"ind1":"0","ind2":" ","subfields":[{"a":"Petrus Alfonsi,"},{"d":"1062-1110?"}]}},{"240":{"ind1":"1","ind2":"0","subfields":[{"a":"Disciplina Clericalis."},{"l":"English"}]}},{"245":{"ind1":"1","ind2":"4","subfields":[{"a":"The scholar's guide."},{"b":"A translation of the twelfth-century Disciplina Clericalis of Pedro Alfonso,"},{"c":"by Joseph Ramon Jones and John Esten Keller."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Toronto,"},{"b":"Pontifical Institute of Mediaeval Studies,"},{"c":"1969."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"117 p."},{"c":"20 cm."}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Includes bibliographical references."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"700":{"ind1":"1","ind2":" ","subfields":[{"a":"Jones, Joseph Ramon,"},{"d":"1935-"}]}},{"700":{"ind1":"1","ind2":" ","subfields":[{"a":"Keller, John Esten,"},{"e":"ed."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"PA8395.P48 D63 1969"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"PA8395.P48 D63 1969"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015005879807"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015011292607"},{"r":"ic"},{"d":"20120530"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"c":"SEP"},{"s":"9115"}]}}]}
|
|
79
|
+
{"leader":"01217nam a22004331 4500","fields":[{"001":"000001659"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1969 nyu b 00110 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"69019912"}]}},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"0030771153"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0118050-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159819948"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00118050"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-nrlf.b146119964"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"P291"},{"b":".C58"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"415"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Cook, Walter Anthony,"},{"d":"1922-"}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Introduction to tagmemic analysis"},{"c":"[by] Walter A. Cook."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Holt, Rinehart and Winston"},{"c":"[1969]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"viii, 210 p."},{"c":"23 cm."}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"Transatlantic series in linguistics"}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Bibliography: p. 200-204."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Tagmemics"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"BUHR"},{"c":"GRAD"},{"h":"P 160 .C77 1969"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"P 160 .C77 1969"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015013397750"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015030740339"},{"r":"ic"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
80
|
+
{"leader":"00937nam a22003491 4500","fields":[{"001":"000003028"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1971 nyu |00011 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"78156496"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0208418-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159821539"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00208418"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"PZ3.V398"},{"b":"Mo"},{"a":"PS3543.A67"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"813/.5/2"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Varandyan, Emmanuel P."}]}},{"245":{"ind1":"1","ind2":"4","subfields":[{"a":"The Moon sails;"},{"b":"a novel,"},{"c":"by Emmanuel P. Varandyan."}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"[1st ed.]"}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Delmar, N.Y.,"},{"b":"Pinnacle,"},{"c":"1971."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"251 p."},{"c":"24 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"852":{"ind1":"1","ind2":" ","subfields":[{"a":"MiU"},{"b":"BUHR"},{"c":"GRAD"},{"h":"828 V288mn, 1971"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015030715380"},{"r":"ic"},{"d":"20120530"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
81
|
+
{"leader":"01141nam a22004091 4500","fields":[{"001":"000003441"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715c19681967pau |00000 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"68010619"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0237566-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159822019"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00237566"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-nrlf-ucscb167381271"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"HE2751"},{"b":".L9"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"385/.0973"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Lyon, Peter,"},{"d":"1915-"}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"To hell in a day coach;"},{"b":"an exasperated look at American railroads."}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"[1st ed.]"}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Philadelphia,"},{"b":"Lippincott,"},{"c":"1968 [c1967]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"vii, 324 p."},{"c":"22 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Railroads"},{"z":"United States"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"SPEC"},{"c":"RARE"},{"h":"HE 2751 .L98"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"SPEC"},{"c":"THC"},{"h":"HE 2751 .L98"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"a":"uc1"},{"b":"SDR"},{"c":"NRLF"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015023095238"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"uc1.b4912198"},{"r":"ic"},{"d":"20111204"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
82
|
+
{"leader":"01692nam a22005291 4500","fields":[{"001":"000003823"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1967 nyu b 00010 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"67025457"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0264219-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159822454"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00264219"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-nrlfGLAD187507-B"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"043":{"ind1":" ","ind2":" ","subfields":[{"a":"n-us---"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"HV4194.A3"},{"b":"D3 1967"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"362/.9/73"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Davis, Allen Freeman,"},{"d":"1931-"}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Spearheads for reform;"},{"b":"the social settlements and the progressive movement, 1890-1914"},{"c":"[by] Allen F. Davis."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Oxford University Press,"},{"c":"1967."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"xviii, 322 p."},{"c":"22 cm."}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"Urban life in America series"}]}},{"502":{"ind1":" ","ind2":" ","subfields":[{"a":"Issued in microfilm form as thesis, University of Wisconsin, 1960."}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"\"A note on sources\": p. 247-255. Bibliography: p. 259-304."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Social settlements"}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Progressivism (United States politics)"}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Cities and towns"},{"z":"United States."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"HV 4194 .D26"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"HV 4194 .D26"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"UGL"},{"h":"HV 4194 .D26"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"HV 4194 .D26"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015002281593"},{"r":"ic"},{"d":"20090807"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015014594108"},{"r":"ic"},{"d":"20090807"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015016230438"},{"r":"ic"},{"d":"20120419"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
83
|
+
{"leader":"01227nam a22004211 4500","fields":[{"001":"000004152"},{"003":"MiU"},{"005":"19890605000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715|1960||||||| |||||||eng|u"},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"60005725"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0289130-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159822835"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00289130"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-nrlf.b120345171"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"OWibfC"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Lyon, Bryce Dale,"},{"d":"1920-"}]}},{"245":{"ind1":"1","ind2":"2","subfields":[{"a":"A constitutional and legal history of medieval England."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Harper"},{"c":"[1960]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"671p."},{"b":"illus."},{"c":"25 cm."}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Includes bibliography."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Law"},{"z":"Great Britain"},{"x":"History"}]}},{"651":{"ind1":" ","ind2":"0","subfields":[{"a":"Great Britain"},{"x":"Politics and government"},{"y":"To 1485."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"JN 137 .L98"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"JN 137 .L98"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"a":"uc1"},{"b":"SDR"},{"c":"NRLF"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015004930999"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015066017214"},{"r":"ic"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"z":"c.3"},{"u":"uc1.b3457094"},{"r":"ic"},{"d":"20100514"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
84
|
+
{"leader":"01517nam a22004931 4500","fields":[{"001":"000004309"},{"003":"MiU"},{"005":"20120524152322.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1964 nyua j 000 1 eng u"},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"64019711"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0301132-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159823014"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00301132"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"ODaWU"},{"d":"InLS"},{"d":"*OCL*"},{"d":"MiU"},{"d":"CStRLIN"},{"d":"EYM"}]}},{"099":{"ind1":" ","ind2":"0","subfields":[{"a":"P Z7 .F5768 H3"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Fitzhugh, Louise."}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Harriet, the spy /"},{"c":"written and illustrated by Louise Fitzhugh."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York :"},{"b":"Harper & Row,"},{"c":"1964."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"298 p. :"},{"b":"ill. ;"},{"c":"21 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"590":{"ind1":" ","ind2":" ","subfields":[{"a":"SPEC WLPR: In the Lee Walp Family Juvenile Literature Collection. Gift of the Lee Walp Family."}]}},{"590":{"ind1":" ","ind2":" ","subfields":[{"a":"SPEC WLPR: Lee Walp’s clippings and notes laid in."}]}},{"590":{"ind1":" ","ind2":" ","subfields":[{"a":"SPEC WLPR: In dust jacket."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Friendship"},{"v":"Juvenile fiction."}]}},{"651":{"ind1":" ","ind2":"0","subfields":[{"a":"New York (N.Y.)"},{"v":"Juvenile fiction."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"UGL"},{"h":"PZ 7 .F555"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"UGL"},{"h":"PZ 7 .F555"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"UGL"},{"c":"CLC"},{"h":"PZ 7 .F555"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"PZ 7 .F555"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"SPEC"},{"c":"WLPR"},{"h":"P Z7 .F5768 H3"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20120524"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015058018790"},{"r":"ic"},{"d":"20120530"}]}},{"997":{"ind1":" ","ind2":" ","subfields":[{"a":"MARS"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
85
|
+
{"leader":"01122nam a22003851 4500","fields":[{"001":"000004964"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715|1965||||||| |||||||eng|u"},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"65023062"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0345135-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159823753"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00345135"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"OUrC"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Nussbaum, Allen."}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Electromagnetic theory for engineers and scientists."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Englewood Cliffs, N. J.,"},{"b":"Prentice-Hall"},{"c":"[1965]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"xiii, 312 p."},{"b":"illus."}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"Microwaves and fields series"}]}},{"500":{"ind1":" ","ind2":" ","subfields":[{"a":"Prentice-Hall electrical engineering series."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Electromagnetic theory"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"SCI"},{"c":"BKS"},{"h":"QC 670.N975"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"SCI"},{"c":"BKS"},{"h":"QC 670 .N975"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015017245518"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015017270458"},{"r":"ic"},{"d":"20100306"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
86
|
+
{"leader":"00920nam a22003371 4500","fields":[{"001":"000005123"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715|1965||||||| |||||||eng|u"},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"65018827"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0358204-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159823931"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00358204"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"ODaWU"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Potter, Stephen,"},{"d":"1900-1969."}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Coleridge and S.T.C."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Russell & Russell,"},{"c":"1965."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"284 p."}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Bibliography: p. 281-282."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"600":{"ind1":"1","ind2":"0","subfields":[{"a":"Coleridge, Samuel Taylor,"},{"d":"1772-1834."}]}},{"852":{"ind1":"1","ind2":" ","subfields":[{"a":"MiU"},{"b":"BUHR"},{"c":"GRAD"},{"h":"828 C693O P87 1965"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015030723566"},{"r":"ic"},{"d":"20120530"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
87
|
+
{"leader":"00919nam a22003251 4500","fields":[{"001":"000005617"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715|1971||||||| |||||||eng|u"},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0400752-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159824485"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00400752"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"OU"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Schlesinger, Janet."}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Challenge to the urban orchestra;"},{"b":"the case of the Pittsburgh Symphony."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"[Pittsburgh?,"},{"c":"c1971]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"163 p."},{"c":"29 cm."}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Bibliography: p. 158-163."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"610":{"ind1":"2","ind2":"0","subfields":[{"a":"Pittsburgh Symphony Orchestra."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"BUHR"},{"c":"MUSI"},{"h":"ML 200.8 .P69 S34"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015007987756"},{"r":"ic"},{"d":"20120525"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
88
|
+
{"leader":"01356nam a22003851 4500","fields":[{"001":"000005933"},{"003":"MiU"},{"005":"19990430000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715|1957||||||| |||||||eng|u"},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0424414-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159824847"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00424414"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"OWorP"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Cunningham, Noble E"}]}},{"245":{"ind1":"1","ind2":"4","subfields":[{"a":"The Jeffersonian Republicans;"},{"b":"the formation of party organization, 1789-1801,"},{"c":"by Noble E. Cunningham."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Chapel Hill,"},{"b":"Published for the Institute of Early American History and Culture at Williamsburg by the Univ. of N. Car. Pr."},{"c":"[c1957]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"x, 279 p."},{"b":"facsims."},{"c":"24 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"610":{"ind1":"2","ind2":"0","subfields":[{"a":"Democratic Party (U.S.)"},{"x":"History."}]}},{"651":{"ind1":" ","ind2":"0","subfields":[{"a":"United States"},{"x":"Politics and government"},{"y":"1789-1809."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Political parties"},{"z":"United States"},{"x":"History."}]}},{"710":{"ind1":"2","ind2":" ","subfields":[{"a":"Institute of Early American History and Culture (Williamsburg, Va.)"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"JK 2316 .C97"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"JK 2316 .C97"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015007045035"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015066018212"},{"r":"ic"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
89
|
+
{"leader":"01058nam a22003731 4500","fields":[{"001":"000006347"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715|1972||||||| |||||||eng|u"},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0477263-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159825319"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00477263"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"OCX"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"417/.7"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Cottrell, Leonard."}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Reading the past;"},{"b":"the story of deciphering ancient languages"},{"c":"[by] Leonard Cottrell."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"London,"},{"b":"J. M. Dent & Sons"},{"c":"[1972]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"viii, 182 p."},{"b":"illus."},{"c":"24 cm."}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Bibliography: p. 171-173."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Hieroglyphics."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Cuneiform writing"}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Alphabet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Writing"},{"x":"History"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"P211 .C84 1972"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015003847020"},{"r":"ic"},{"d":"20120530"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
90
|
+
{"leader":"01837nam a22004571 4500","fields":[{"001":"000006850"},{"003":"MiU"},{"005":"20010806000000.0"},{"008":"880715s1967 ilu b 00010 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"66020582"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0513381-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159825875"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00513381"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-umdb.b10778883"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"041":{"ind1":"1","ind2":" ","subfields":[{"a":"eng"},{"h":"rus"}]}},{"043":{"ind1":" ","ind2":" ","subfields":[{"a":"e-ur---"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Schwarz, Solomon M."}]}},{"240":{"ind1":"1","ind2":"0","subfields":[{"a":"Menʹshevizm i bolʹshevizm v ikh otnoshenii k massovomu rabochemu dvizhenii︠u︡."},{"l":"English"}]}},{"245":{"ind1":"1","ind2":"4","subfields":[{"a":"The Russian Revolution of 1905 :"},{"b":"the workers' movement and the formation of Bolshevism and Menshevism /"},{"c":"[by] Solomon M. Schwarz ; Translated by Gertrude Vakar."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Chicago :"},{"b":"University of Chicago Press,"},{"c":"[1967]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"xxii, 361 p. ;"},{"c":"24 cm."}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"Hoover Institution publications"}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"History of Menshevism"}]}},{"500":{"ind1":" ","ind2":" ","subfields":[{"a":"Translation and expansion of Menʹshevizm i bolʹshevizm v ikh otnoshenii k massovomu rabochemu dvizhenii︠u︡."}]}},{"500":{"ind1":" ","ind2":" ","subfields":[{"a":"\"One of a series arising from the work of the Inter-university Project on the History of the Menshevik Movement.\""}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Includes bibliographical references."}]}},{"610":{"ind1":"2","ind2":"0","subfields":[{"a":"Rossiĭskai︠a︡ sot︠s︡ial-demokraticheskai︠a︡ rabochai︠a︡ partii︠a︡."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Labor movement"},{"z":"Soviet Union."}]}},{"651":{"ind1":" ","ind2":"0","subfields":[{"a":"Russia"},{"x":"History"},{"y":"Revolution, 1905-1907."}]}},{"710":{"ind1":"2","ind2":" ","subfields":[{"a":"Inter-university Project on the History of the Menshevik Movement."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"JN6598.R8 S423"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"JN6598.R8 S423"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"SPEC"},{"c":"LABD"},{"h":"JN 6598 .R8 S423"},{"x":"30215341"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9615"}]}}]}
|
|
91
|
+
{"leader":"01209nam a22003851 4500","fields":[{"001":"000008015"},{"003":"MiU"},{"005":"19890306000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1973 nyua d |00000 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"73153601"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0590313-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159827164"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00590313"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"PE1625"},{"b":".S713 1973"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"423"}]}},{"245":{"ind1":"0","ind2":"0","subfields":[{"a":"Funk & Wagnalls standard dictionary of the English language."}]}},{"250":{"ind1":" ","ind2":" ","subfields":[{"a":"International ed.,"},{"b":"with special supplementary features."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Funk & Wagnalls"},{"c":"[1973]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"2 v. (xx, 1695 p.)"},{"b":"illus. (part col.)"},{"c":"29 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"English language"},{"x":"Dictionaries"}]}},{"740":{"ind1":"0","ind2":" ","subfields":[{"a":"Funk and Wagnalls standard dictionary of the English language."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"PE 1625 .S785 1973"},{"x":"tr. fr. GLRF 9-5-97"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"DI"},{"b":"Dictionaries"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"z":"v.1"},{"u":"mdp.39015066305270"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"z":"v.2"},{"u":"mdp.39015066305429"},{"r":"ic"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
92
|
+
{"leader":"01009nam a22003731 4500","fields":[{"001":"000008105"},{"003":"MiU"},{"005":"20071115093023.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1973 nyu |00010 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"72014035"}]}},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"0442214707"},{"c":"$5.95"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0595319-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159827258"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00595319"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-wu88160"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"043":{"ind1":" ","ind2":" ","subfields":[{"a":"n-us---"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"HQ536"},{"b":".B86"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"301.42/0973"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Burger, Robert E."}]}},{"245":{"ind1":"1","ind2":"4","subfields":[{"a":"The love contract;"},{"b":"handbook for a liberated marriage"},{"c":"[by] Robert E. Burger."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Van Nostrand Reinhold"},{"c":"[1973]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"ix, 107 p."},{"c":"24 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Marriage"},{"z":"United States"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"a":"wu"},{"b":"SDR"},{"c":"WU"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"wu.89031137284"},{"r":"ic"},{"d":"20120530"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
93
|
+
{"leader":"01115nam a22003731 4500","fields":[{"001":"000008459"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715|1970||||||| |||||||ita|u"},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"76881291"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0615380-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159827651"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00615380"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-nrlfGLAD17038931-B"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"c":"OCU"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"050":{"ind1":" ","ind2":"4","subfields":[{"a":"PA2402"},{"b":".S21"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Savelli, Angelo,"},{"d":"1930-"}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Nuovissime interpretazioni etrusche."},{"b":"Le lamine d'oro di Pyrgi, l'iscrizione estrusco-latina del Lapis Niger, la stele greco-tirrena di Lemno."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"Bologna,"},{"b":"Tip. Accorsi,"},{"c":"1970."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"78 p."},{"c":"24 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Inscriptions, Etruscan"}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"PA2402 .S21"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"a":"uc1"},{"b":"SDR"},{"c":"NRLF"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015025030563"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"uc1.b3176758"},{"r":"ic"},{"d":"20090915"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
94
|
+
{"leader":"01202nam a22004211 4500","fields":[{"001":"000009080"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1972 enka b |00110 engx "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"73160987"}]}},{"015":{"ind1":" ","ind2":" ","subfields":[{"a":"B73-00589"}]}},{"020":{"ind1":" ","ind2":" ","subfields":[{"a":"0140806652"},{"c":"£1.25"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0651225-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159828340"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00651225"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"},{"d":"CStRLIN"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"P41"},{"b":".P72"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"301.2/1"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Pride, J. B. E."}]}},{"245":{"ind1":"1","ind2":"0","subfields":[{"a":"Sociolinguistics: selected readings;"},{"c":"edited by J. B. Pride and Janet Holmes."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"[Harmondsworth,]"},{"b":"Penguin,"},{"c":"[1972]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"381 p."},{"b":"illus."},{"c":"20 cm. index."}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"Penguin education"}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"Penguin modern linguistics readings"}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Bibliography: p. 367-369."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"650":{"ind1":" ","ind2":"0","subfields":[{"a":"Sociolinguistics."}]}},{"700":{"ind1":"1","ind2":" ","subfields":[{"a":"Holmes, Janet."},{"e":"joint comp."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"P 41 .P946"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015019228280"},{"r":"ic"},{"d":"20120530"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
95
|
+
{"leader":"01075nam a22003851 4500","fields":[{"001":"000009820"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1973 nyu b 00010beng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"73000507"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0695465-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159829137"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00695465"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"PS1291"},{"b":".H8"}]}},{"082":{"ind1":" ","ind2":" ","subfields":[{"a":"811/.2"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Hudspeth, Robert N."}]}},{"245":{"ind1":"0","ind2":"0","subfields":[{"a":"Ellery Channing,"},{"c":"by Robert N. Hudspeth."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Twayne Publishers"},{"c":"[1973]"}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"182 p."},{"c":"21 cm."}]}},{"490":{"ind1":"0","ind2":" ","subfields":[{"a":"Twayne's United States authors series,"},{"v":"TUSAS 223"}]}},{"504":{"ind1":" ","ind2":" ","subfields":[{"a":"Bibliography: p. 171-177."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"600":{"ind1":"1","ind2":"0","subfields":[{"a":"Channing, William Ellery,"},{"d":"1817-1901."}]}},{"852":{"ind1":"1","ind2":" ","subfields":[{"a":"MiU"},{"b":"BUHR"},{"c":"GRAD"},{"h":"828 C458O H88"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BI"},{"b":"Biography"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015030727799"},{"r":"ic"},{"d":"20120530"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9125"}]}}]}
|
|
96
|
+
{"leader":"01215nam a22004091 4500","fields":[{"001":"000010179"},{"003":"MiU"},{"005":"19880715000000.0"},{"006":"m d "},{"007":"cr bn ---auaua"},{"008":"880715s1962 nyu 00001 eng "},{"010":{"ind1":" ","ind2":" ","subfields":[{"a":"62009606/L/r66"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(RLIN)MIUG0710844-B"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(CaOTULAS)159829527"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"(OCoLC)ocm00710844"}]}},{"035":{"ind1":" ","ind2":" ","subfields":[{"a":"sdr-ucsc.b15850766"}]}},{"040":{"ind1":" ","ind2":" ","subfields":[{"a":"DLC"},{"c":"DLC"},{"d":"MiU"}]}},{"041":{"ind1":"1","ind2":" ","subfields":[{"a":"enggre"}]}},{"050":{"ind1":"0","ind2":" ","subfields":[{"a":"PZ3.K1884"},{"b":"Sai"}]}},{"100":{"ind1":"1","ind2":" ","subfields":[{"a":"Kazantzakis, Nikos,"},{"d":"1883-1957."}]}},{"240":{"ind1":"0","ind2":"3","subfields":[{"a":"Ho phtochoules tou Theou."},{"l":"English"}]}},{"245":{"ind1":"0","ind2":"0","subfields":[{"a":"Saint Francis,"},{"b":"a novel."},{"c":"Translated from the Greek by P. A. Bien."}]}},{"260":{"ind1":" ","ind2":" ","subfields":[{"a":"New York,"},{"b":"Simon and Schuster,"},{"c":"1962."}]}},{"300":{"ind1":" ","ind2":" ","subfields":[{"a":"379 p."},{"c":"22 cm."}]}},{"538":{"ind1":" ","ind2":" ","subfields":[{"a":"Mode of access: Internet."}]}},{"600":{"ind1":"0","ind2":"0","subfields":[{"a":"Francis,"},{"c":"of Assisi, Saint,"},{"d":"1182-1226"},{"x":"Fiction."}]}},{"852":{"ind1":"0","ind2":" ","subfields":[{"a":"MiU"},{"b":"HATCH"},{"c":"GRAD"},{"h":"PA 5610 .K23 P53"}]}},{"852":{"ind1":" ","ind2":" ","subfields":[{"a":"uc1"},{"b":"SDR"},{"c":"UCSC"}]}},{"970":{"ind1":" ","ind2":" ","subfields":[{"a":"BK"},{"b":"Book"}]}},{"971":{"ind1":" ","ind2":" ","subfields":[{"a":"MiU"}]}},{"972":{"ind1":" ","ind2":" ","subfields":[{"c":"20040625"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"HT"},{"b":"avail_ht"}]}},{"973":{"ind1":" ","ind2":" ","subfields":[{"a":"AC"},{"b":"avail_circ"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"mdp.39015002669383"},{"r":"ic"},{"d":"20120530"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"uc1.32106006141748"},{"r":"ic"},{"d":"20100906"}]}},{"974":{"ind1":" ","ind2":" ","subfields":[{"u":"uc1.32106016310622"},{"r":"ic"},{"d":"20100906"}]}},{"998":{"ind1":" ","ind2":" ","subfields":[{"s":"9665"}]}}]}
|
|
97
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'marc'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'zlib'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Read newline-delimited JSON file, where each line is a marc-in-json string.
|
|
7
|
+
# UTF-8 encoding is required.
|
|
8
|
+
|
|
9
|
+
class Traject::NDJReader
|
|
10
|
+
include Enumerable
|
|
11
|
+
|
|
12
|
+
def initialize(input_stream, settings)
|
|
13
|
+
@settings = settings
|
|
14
|
+
@input_stream = input_stream
|
|
15
|
+
if @settings['command_line.filename'] =~ /\.gz$/
|
|
16
|
+
@input_stream = Zlib::GzipReader.new(@input_stream, :external_encoding => "UTF-8")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def logger
|
|
21
|
+
@logger ||= (@settings[:logger] || Yell.new(STDERR, :level => "gt.fatal")) # null logger)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def each
|
|
25
|
+
unless block_given?
|
|
26
|
+
return enum_for(:each)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@input_stream.each_with_index do |json, i|
|
|
30
|
+
begin
|
|
31
|
+
yield MARC::Record.new_from_hash(JSON.parse(json))
|
|
32
|
+
rescue Exception => e
|
|
33
|
+
self.logger.error("Problem with JSON record on line #{i}: #{e.message}")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# A Null writer that does absolutely nothing with records given to it,
|
|
2
|
+
# just drops em on the floor.
|
|
3
|
+
class Traject::NullWriter
|
|
4
|
+
attr_reader :settings
|
|
5
|
+
|
|
6
|
+
def initialize(argSettings)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def serialize(context)
|
|
11
|
+
# null
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def put(context)
|
|
15
|
+
# null
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def close
|
|
19
|
+
# null
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# From http://redcorundum.blogspot.com/2006/05/kernelqualifiedconstget.html
|
|
2
|
+
# Adapted into a module, rather than monkey patching it into Kernel
|
|
3
|
+
#
|
|
4
|
+
# Method to take a string constant name, including :: qualifications, and
|
|
5
|
+
# look up the actual constant. Looks up relative to current file.
|
|
6
|
+
# Respects leading ::. Etc.
|
|
7
|
+
#
|
|
8
|
+
# class Something
|
|
9
|
+
# include Traject::QualifiedConstGet
|
|
10
|
+
#
|
|
11
|
+
# def foo
|
|
12
|
+
# #...
|
|
13
|
+
# klass = qualified_const_get("Foo::Bar")
|
|
14
|
+
# #...
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
module Traject::QualifiedConstGet
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def qualified_const_get(str)
|
|
21
|
+
path = str.to_s.split('::')
|
|
22
|
+
from_root = path[0].empty?
|
|
23
|
+
if from_root
|
|
24
|
+
from_root = []
|
|
25
|
+
path = path[1..-1]
|
|
26
|
+
else
|
|
27
|
+
start_ns = ((Class === self)||(Module === self)) ? self : self.class
|
|
28
|
+
from_root = start_ns.to_s.split('::')
|
|
29
|
+
end
|
|
30
|
+
until from_root.empty?
|
|
31
|
+
begin
|
|
32
|
+
return (from_root+path).inject(Object) { |ns,name| ns.const_get(name) }
|
|
33
|
+
rescue NameError
|
|
34
|
+
from_root.delete_at(-1)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
path.inject(Object) { |ns,name| ns.const_get(name) }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
require 'yell'
|
|
2
|
+
|
|
3
|
+
require 'traject'
|
|
4
|
+
require 'traject/util'
|
|
5
|
+
require 'traject/qualified_const_get'
|
|
6
|
+
require 'traject/thread_pool'
|
|
7
|
+
|
|
8
|
+
require 'json'
|
|
9
|
+
require 'httpclient'
|
|
10
|
+
|
|
11
|
+
require 'uri'
|
|
12
|
+
require 'thread' # for Mutex/Queue
|
|
13
|
+
require 'concurrent' # for atomic_fixnum
|
|
14
|
+
|
|
15
|
+
# Write to Solr using the JSON interface; only works for Solr >= 3.2
|
|
16
|
+
#
|
|
17
|
+
# This should work under both MRI and JRuby, with JRuby getting much
|
|
18
|
+
# better performance due to the threading model.
|
|
19
|
+
#
|
|
20
|
+
# Relevant settings
|
|
21
|
+
#
|
|
22
|
+
# * solr.url (optional if solr.update_url is set) The URL to the solr core to index into
|
|
23
|
+
#
|
|
24
|
+
# * solr.update_url: The actual update url. If unset, we'll first see if
|
|
25
|
+
# "#{solr.url}/update/json" exists, and if not use "#{solr.url}/update"
|
|
26
|
+
#
|
|
27
|
+
# * solr_writer.batch_size: How big a batch to send to solr. Default is 100.
|
|
28
|
+
# My tests indicate that this setting doesn't change overall index speed by a ton.
|
|
29
|
+
#
|
|
30
|
+
# * solr_writer.thread_pool: How many threads to use for the writer. Default is 1.
|
|
31
|
+
# Likely useful even under MRI since thread will be waiting on Solr for some time.
|
|
32
|
+
#
|
|
33
|
+
# * solr_writer.max_skipped: How many records skipped due to errors before we
|
|
34
|
+
# bail out with a fatal error? Set to -1 for unlimited skips. Default 0,
|
|
35
|
+
# raise and abort on a single record that could not be added to Solr.
|
|
36
|
+
#
|
|
37
|
+
# * solr_writer.commit_on_close: Set to true (or "true") if you want to commit at the
|
|
38
|
+
# end of the indexing run. (Old "solrj_writer.commit_on_close" supported for backwards
|
|
39
|
+
# compat only.)
|
|
40
|
+
#
|
|
41
|
+
# * solr_writer.commit_timeout: If commit_on_close, how long to wait for Solr before
|
|
42
|
+
# giving up as a timeout. Default 10 minutes. Solr can be slow.
|
|
43
|
+
#
|
|
44
|
+
# * solr_json_writer.http_client Mainly intended for testing, set your own HTTPClient
|
|
45
|
+
# or mock object to be used for HTTP.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Traject::SolrJsonWriter
|
|
49
|
+
include Traject::QualifiedConstGet
|
|
50
|
+
|
|
51
|
+
DEFAULT_MAX_SKIPPED = 0
|
|
52
|
+
DEFAULT_BATCH_SIZE = 100
|
|
53
|
+
|
|
54
|
+
# The passed-in settings
|
|
55
|
+
attr_reader :settings, :thread_pool_size
|
|
56
|
+
|
|
57
|
+
# A queue to hold documents before sending to solr
|
|
58
|
+
attr_reader :batched_queue
|
|
59
|
+
|
|
60
|
+
def initialize(argSettings)
|
|
61
|
+
@settings = Traject::Indexer::Settings.new(argSettings)
|
|
62
|
+
|
|
63
|
+
# Set max errors
|
|
64
|
+
@max_skipped = (@settings['solr_writer.max_skipped'] || DEFAULT_MAX_SKIPPED).to_i
|
|
65
|
+
if @max_skipped < 0
|
|
66
|
+
@max_skipped = nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
@http_client = @settings["solr_json_writer.http_client"] || HTTPClient.new
|
|
70
|
+
|
|
71
|
+
@batch_size = (settings["solr_writer.batch_size"] || DEFAULT_BATCH_SIZE).to_i
|
|
72
|
+
@batch_size = 1 if @batch_size < 1
|
|
73
|
+
|
|
74
|
+
# Store error count in an AtomicInteger, so multi threads can increment
|
|
75
|
+
# it safely, if we're threaded.
|
|
76
|
+
@skipped_record_incrementer = Concurrent::AtomicFixnum.new(0)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# How many threads to use for the writer?
|
|
80
|
+
# if our thread pool settings are 0, it'll just create a null threadpool that
|
|
81
|
+
# executes in calling context.
|
|
82
|
+
@thread_pool_size = (@settings["solr_writer.thread_pool"] || 1).to_i
|
|
83
|
+
|
|
84
|
+
@batched_queue = Queue.new
|
|
85
|
+
@thread_pool = Traject::ThreadPool.new(@thread_pool_size)
|
|
86
|
+
|
|
87
|
+
# old setting solrj_writer supported for backwards compat, as we make
|
|
88
|
+
# this the new default writer.
|
|
89
|
+
@commit_on_close = (settings["solr_writer.commit_on_close"] || settings["solrj_writer.commit_on_close"]).to_s == "true"
|
|
90
|
+
|
|
91
|
+
# Figure out where to send updates
|
|
92
|
+
@solr_update_url = self.determine_solr_update_url
|
|
93
|
+
|
|
94
|
+
logger.info(" #{self.class.name} writing to '#{@solr_update_url}' in batches of #{@batch_size} with #{@thread_pool_size} bg threads")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# Add a single context to the queue, ready to be sent to solr
|
|
99
|
+
def put(context)
|
|
100
|
+
@thread_pool.raise_collected_exception!
|
|
101
|
+
|
|
102
|
+
@batched_queue << context
|
|
103
|
+
if @batched_queue.size >= @batch_size
|
|
104
|
+
batch = Traject::Util.drain_queue(@batched_queue)
|
|
105
|
+
@thread_pool.maybe_in_thread_pool(batch) {|batch_arg| send_batch(batch_arg) }
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Send the given batch of contexts. If something goes wrong, send
|
|
110
|
+
# them one at a time.
|
|
111
|
+
# @param [Array<Traject::Indexer::Context>] an array of contexts
|
|
112
|
+
def send_batch(batch)
|
|
113
|
+
return if batch.empty?
|
|
114
|
+
json_package = JSON.generate(batch.map { |c| c.output_hash })
|
|
115
|
+
begin
|
|
116
|
+
resp = @http_client.post @solr_update_url, json_package, "Content-type" => "application/json"
|
|
117
|
+
rescue StandardError => exception
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
if exception || resp.status != 200
|
|
121
|
+
error_message = exception ?
|
|
122
|
+
Traject::Util.exception_to_log_message(exception) :
|
|
123
|
+
"Solr response: #{resp.status}: #{resp.body}"
|
|
124
|
+
|
|
125
|
+
logger.error "Error in Solr batch add. Will retry documents individually at performance penalty: #{error_message}"
|
|
126
|
+
|
|
127
|
+
batch.each do |c|
|
|
128
|
+
send_single(c)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# Send a single context to Solr, logging an error if need be
|
|
135
|
+
# @param [Traject::Indexer::Context] c The context whose document you want to send
|
|
136
|
+
def send_single(c)
|
|
137
|
+
json_package = JSON.generate([c.output_hash])
|
|
138
|
+
begin
|
|
139
|
+
resp = @http_client.post @solr_update_url, json_package, "Content-type" => "application/json"
|
|
140
|
+
# Catch Timeouts and network errors as skipped records, but otherwise
|
|
141
|
+
# allow unexpected errors to propagate up.
|
|
142
|
+
rescue HTTPClient::TimeoutError, SocketError, Errno::ECONNREFUSED => exception
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
if exception || resp.status != 200
|
|
146
|
+
if exception
|
|
147
|
+
msg = Traject::Util.exception_to_log_message(e)
|
|
148
|
+
else
|
|
149
|
+
msg = "Solr error response: #{resp.status}: #{resp.body}"
|
|
150
|
+
end
|
|
151
|
+
logger.error "Could not add record #{record_id_from_context c} at source file position #{c.position}: #{msg}"
|
|
152
|
+
logger.debug(c.source_record.to_s)
|
|
153
|
+
|
|
154
|
+
@skipped_record_incrementer.increment
|
|
155
|
+
if @max_skipped and skipped_record_count > @max_skipped
|
|
156
|
+
raise RuntimeError.new("#{self.class.name}: Exceeded maximum number of skipped records (#{@max_skipped}): aborting")
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# Get the logger from the settings, or default to an effectively null logger
|
|
165
|
+
def logger
|
|
166
|
+
settings["logger"] ||= Yell.new(STDERR, :level => "gt.fatal") # null logger
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Returns MARC 001, then a slash, then output_hash["id"] -- if both
|
|
170
|
+
# are present. Otherwise may return just one, or even an empty string.
|
|
171
|
+
def record_id_from_context(context)
|
|
172
|
+
marc_id = context.source_record && context.source_record['001'] && context.source_record['001'].value
|
|
173
|
+
output_id = context.output_hash["id"]
|
|
174
|
+
|
|
175
|
+
return [marc_id, output_id].compact.join("/")
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# On close, we need to (a) raise any exceptions we might have, (b) send off
|
|
180
|
+
# the last (possibly empty) batch, and (c) commit if instructed to do so
|
|
181
|
+
# via the solr_writer.commit_on_close setting.
|
|
182
|
+
def close
|
|
183
|
+
@thread_pool.raise_collected_exception!
|
|
184
|
+
|
|
185
|
+
# Finish off whatever's left. Do it in the thread pool for
|
|
186
|
+
# consistency, and to ensure expected order of operations, so
|
|
187
|
+
# it goes to the end of the queue behind any other work.
|
|
188
|
+
batch = Traject::Util.drain_queue(@batched_queue)
|
|
189
|
+
if batch.length > 0
|
|
190
|
+
@thread_pool.maybe_in_thread_pool { send_batch(batch) }
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Wait for shutdown, and time it.
|
|
194
|
+
logger.debug "#{self.class.name}: Shutting down thread pool, waiting if needed..."
|
|
195
|
+
elapsed = @thread_pool.shutdown_and_wait
|
|
196
|
+
if elapsed > 60
|
|
197
|
+
logger.warn "Waited #{elapsed} seconds for all threads, you may want to increase solr_writer.thread_pool (currently #{@settings["solr_writer.thread_pool"]})"
|
|
198
|
+
end
|
|
199
|
+
logger.debug "#{self.class.name}: Thread pool shutdown complete"
|
|
200
|
+
logger.warn "#{self.class.name}: #{skipped_record_count} skipped records" if skipped_record_count > 0
|
|
201
|
+
|
|
202
|
+
# check again now that we've waited, there could still be some
|
|
203
|
+
# that didn't show up before.
|
|
204
|
+
@thread_pool.raise_collected_exception!
|
|
205
|
+
|
|
206
|
+
# Commit if we're supposed to
|
|
207
|
+
if @commit_on_close
|
|
208
|
+
commit
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# Send a commit
|
|
214
|
+
def commit
|
|
215
|
+
logger.info "#{self.class.name} sending commit to solr at url #{@solr_update_url}..."
|
|
216
|
+
|
|
217
|
+
original_timeout = @http_client.receive_timeout
|
|
218
|
+
|
|
219
|
+
@http_client.receive_timeout = (settings["commit_timeout"] || (10 * 60)).to_i
|
|
220
|
+
|
|
221
|
+
resp = @http_client.get(@solr_update_url, {"commit" => 'true'})
|
|
222
|
+
unless resp.status == 200
|
|
223
|
+
raise RuntimeError.new("Could not commit to Solr: #{resp.status} #{resp.body}")
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
@http_client.receive_timeout = original_timeout
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# Return count of encountered skipped records. Most accurate to call
|
|
231
|
+
# it after #close, in which case it should include full count, even
|
|
232
|
+
# under async thread_pool.
|
|
233
|
+
def skipped_record_count
|
|
234
|
+
@skipped_record_incrementer.value
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# Relatively complex logic to determine if we have a valid URL and what it is
|
|
239
|
+
def determine_solr_update_url
|
|
240
|
+
if settings['solr.update_url']
|
|
241
|
+
check_solr_update_url(settings['solr.update_url'])
|
|
242
|
+
else
|
|
243
|
+
derive_solr_update_url_from_solr_url(settings['solr.url'])
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# If we've got a solr.update_url, make sure it's ok
|
|
249
|
+
def check_solr_update_url(url)
|
|
250
|
+
unless url =~ /^#{URI::regexp}$/
|
|
251
|
+
raise ArgumentError.new("#{self.class.name} setting `solr.update_url` doesn't look like a URL: `#{url}`")
|
|
252
|
+
end
|
|
253
|
+
url
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def derive_solr_update_url_from_solr_url(url)
|
|
257
|
+
# Nil? Then we bail
|
|
258
|
+
if url.nil?
|
|
259
|
+
raise ArgumentError.new("#{self.class.name}: Neither solr.update_url nor solr.url set; need at least one")
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# Not a URL? Bail
|
|
263
|
+
unless url =~ /^#{URI::regexp}$/
|
|
264
|
+
raise ArgumentError.new("#{self.class.name} setting `solr.url` doesn't look like a URL: `#{url}`")
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# First, try the /update/json handler
|
|
268
|
+
candidate = [url.chomp('/'), 'update', 'json'].join('/')
|
|
269
|
+
resp = @http_client.get(candidate)
|
|
270
|
+
if resp.status == 404
|
|
271
|
+
candidate = [url.chomp('/'), 'update'].join('/')
|
|
272
|
+
end
|
|
273
|
+
candidate
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
end
|