在Ruby中,如何使用嵌套数组作为输入递归填充Mongo数据库



我使用Ruby已经有一段时间了,但这是我第一次使用数据库。我已经使用MongoDB玩了一段时间,现在,我已经开始尝试填充一个简单的数据库。

这是我的问题。我有一个包含特定格式数据的文本文件。当我在中读取该文件时,数据存储在嵌套数组中,如下所示:

dataFile = ["sectionName", ["key1", "value1"], ["key2", "value2", ["key3", ["value3A", "value3B"]]]

格式始终是数组的第一个值是字符串,随后的每个值都是数组。每个数组都被格式化为一个键/值对。但是,值可以是一个字符串、两个字符串的数组,也可以是一系列具有自己的键/值数组对的数组。在我读入数据文件之前,我不知道它的任何细节,只是它符合这些规则。

现在,这是我的问题。我想把它读到一个Mongo数据库中,保留这个基本结构。因此,例如,如果我用手做这件事,它会看起来像这样:

newDB = mongo_client.db("newDB")
newCollection = newDB["dataFile1"]
doc = {"section_name" => "sectionName", "key1" => "value1", "key2" => "value2", "key3" => ["value3A", "value3B"]}
ID = newCollection.insert(doc)

我知道必须有一个简单的方法来做到这一点。到目前为止,我一直在尝试各种递归函数来解析数据,将其转换为mongo命令,并尝试填充我的数据库。但它只是感觉笨重,好像有更好的方法。对这个问题有任何见解都将不胜感激。

您为变量dataFile提供的值不是有效的数组,因为它缺少一个右方括号。

如果我们将dataFile的定义作为一行有效的ruby代码,那么下面的代码将产生您所描述的散列。它使用map.with_index访问数组的每个元素,并将该数组转换为一个新的键/值哈希数组。这个转换后的散列数组被平坦化,并使用inject方法转换为单个散列。

dataFile = ["sectionName", ["key1", "value1"], ["key2", "value2", ["key3", ["value3A", "value3B"]]]]
puts dataFile.map.with_index {
|e, ix|
case ix
when 0
{ "section_name" => e }
else
list = []
list.push( { e[0] => e[1] } )
if( e.length > 2 )
list.push(
e[2..e.length-1].map {|p|
{ p[0] => p[1] }
}
)
end
list
end
}.flatten.inject({ }) {
|accum, e|
key = e.keys.first
accum[ key ] = e[ key ]
accum
}.inspect

输出看起来像:

{"section_name"=>"sectionName", "key1"=>"value1", "key2"=>"value2", "key3"=>["value3A", "value3B"]}

对于看起来像这样的输入:

["sectionName", ["key1", "value1"], ["key2", "value2", ["key3", ["value3A", "value3B"]], ["key4", ["value4A", "value4B"]]], ["key5", ["value5A", "value5B"]]]

我们会看到:

{"section_name"=>"sectionName", "key1"=>"value1", "key2"=>"value2", "key3"=>["value3A", "value3B"], "key4"=>["value4A", "value4B"], "key5"=>["value5A", "value5B"]}

注意数组"key3"one_answers"key4",我认为这是一系列数组。如果该结构具有未知深度的数组,那么我们将需要一个不同的实现——当程序遍历这个任意嵌套的数组时,可以使用数组来跟踪位置。

在下面的测试中,请找到两个解决方案。第一个转换为嵌套的Hash,我认为这是您想要的,而不会使输入数据变平。第二个存储键值对,与输入中给出的值完全相同。我选择通过保留键值对来修复缺少的闭合方括号。

这里的主要消息是,虽然MongoDB的顶级数据结构是映射到Ruby Hash的文档根据定义具有键值结构,值可以是任何形状,包括嵌套数组或散列。因此,我希望测试示例能够涵盖这一范围,表明您可以匹配MongoDB中的存储以满足您的需求。

test.rb

require 'mongo'
require 'test/unit'
require 'pp'
class MyTest < Test::Unit::TestCase
def setup
@coll = Mongo::MongoClient.new['test']['test']
@coll.remove
@dataFile = ["sectionName", ["key1", "value1"], ["key2", "value2"], ["key3", ["value3A", "value3B"]]]
@key, *@value = @dataFile
end
test "nested array data as hash value" do
input_doc = {@key => Hash[*@value.flatten(1)]}
@coll.insert(input_doc)
fetched_doc = @coll.find.first
assert_equal(input_doc[@key], fetched_doc[@key])
puts "#{name} fetched hash value doc:"
pp fetched_doc
end
test "nested array data as array value" do
input_doc = {@key => @value}
@coll.insert(input_doc)
fetched_doc = @coll.find.first
assert_equal(input_doc[@key], fetched_doc[@key])
puts "#{name} fetched array doc:"
pp fetched_doc
end
end

ruby test.rb

$ ruby test.rb
Loaded suite test
Started
test: nested array data as array value(MyTest) fetched array doc:
{"_id"=>BSON::ObjectId('5357d4ac7f11ba0678000001'),
"sectionName"=>
[["key1", "value1"], ["key2", "value2"], ["key3", ["value3A", "value3B"]]]}
.test: nested array data as hash value(MyTest) fetched hash value doc:
{"_id"=>BSON::ObjectId('5357d4ac7f11ba0678000002'),
"sectionName"=>
{"key1"=>"value1", "key2"=>"value2", "key3"=>["value3A", "value3B"]}}
.
Finished in 0.009493 seconds.
2 tests, 2 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
210.68 tests/s, 210.68 assertions/s

最新更新