解析镶木木材与GO一起存储在S3中
#serverless #go #s3 #datascience

我知道它是2023年,但是您可以摆脱处理文件。在事件,API和插座的世界中,文件仍然存在作为移动数据的媒介。这是一个非常普遍的。近年来,我发现自己正在处理Apache Parquet格式文件。更具体地说,我经常最终与他们打交道AWS S3。如果您在复制时是所有AWS DMS产品的消费者,您会发现Parquet Format是处理您的数据的好方法,因为它旨在有效地存储和检索。与Golang一起解析镶木木文件的选项太多了,但是我找到了一个我真正喜欢的库,下面的文章将描述如何充分利用它。

一如既往,这是指向Github Repository的链接,如果您想跳过

什么是Apache Parquet

Apache Parquet是一种开源,面向列的数据文件格式,旨在有效的数据存储和检索。它提供有效的数据压缩和编码方案,具有增强的性能,以批量处理复杂的数据。 Parquet有多种语言,包括Java,C ++,Python等

https://parquet.apache.org/

下载镶木石文件

对于使用S3,我真的很喜欢Golang库,称为s3manager。这是SDK documentation。我喜欢它的是,在正常S3库的顶部是更高级别的抽象。例如,要从水桶下载文件,您只需执行此类操作

downloader := s3manager.NewDownloader(sess)
_, err = downloader.DownloadWithContext(ctx, file,
    &s3.GetObjectInput{
        Bucket: aws.String(bucket),
        Key:    aws.String(key),
    })

下载器将将文件放入您在文件参数中的下载WithContext方法中指定的路径中。它只是一个字符串。

用golang解析文件

用golang解析Apache Parquet文件似乎将超级家庭与其他界面的Unmarshalling(例如Dyanamodb和Json)进行分析。对于与DDB的相似之处,您可以在引用的article

中查看如何执行此操作。

解析功能看起来像这样

func ParseFile(fileName string) ([]ParquetUser, error) {
    fr, err := floor.NewFileReader(fileName)
    var fileContent []ParquetUser
    if err != nil {
        return nil, err
    }

    for fr.Next() {
        rec := &ParquetUser{}
        if err := fr.Scan(rec); err != nil {
            // continue along is it's just a malformed row
            if errors.Is(err, ErrIllegalRow) {
                continue
            }
            return nil, err
        }

        fileContent = append(fileContent, *rec)
    }

    return fileContent, nil
}

首先,请注意,我从Parquet-go库打开了一个FileReader。

从那里,我创建了一个切片,用于保持未划分的输出。

然后我们循环和扫描。对于每个扫描调用,都调用了实现Parquet-Go接口的Unmarshall方法。这种方法看起来像这样

func (r *ParquetUser) UnmarshalParquet(obj interfaces.UnmarshalObject) error {
    id, err := obj.GetField("id").Int32()

    if err != nil {
        return errors.New(fmt.Sprintf("error unmarshalling row on field (id)"))
    }

    firstName, err := obj.GetField("firstName").ByteArray()

    if err != nil {
        return errors.New(fmt.Sprintf("error unmarshalling row on field (firstName)"))
    }

    lastName, err := obj.GetField("lastName").ByteArray()

    if err != nil {
        return errors.New(fmt.Sprintf("error unmarshalling row on field (lastName)"))
    }

    role, err := obj.GetField("role").ByteArray()

    if err != nil {
        return errors.New(fmt.Sprintf("error unmarshalling row on field (role)"))
    }

    // note this is a time.Time but comes across as an Int64
    lastUpdated, err := obj.GetField("lastUpdated").Int64()

    if err != nil {
        return errors.New(fmt.Sprintf("error unmarshalling row on field (lastUpdated)"))
    }

    parsed := time.UnixMicro(lastUpdated)

    if err != nil {
        log.WithFields(log.Fields{
            "err": err,
        }).Error("error parsing time")
        return errors.New(fmt.Sprintf("(lastUpdated) is not in the right format"))
    }

    r.Id = int(id)
    r.FirstName = string(firstName)
    r.LastName = string(lastName)
    r.Role = string(role)
    r.LastUpdated = parsed
    return nil
}

实际上并没有太多在获取字段之外的地方,然后将它们放入结构字段。要指出的一件主要的事情是,一个陷入困境的是,最后一个的字段是time.Time。镶木库将时间视为Int64。请注意此行将从图书馆转换为time.Time

的行

parsed := time.UnixMicro(lastUpdated)

运行程序

从那里开始,这只是将所有内容放在一起的问题。这里是main

func main() {
    file, err := DownloadFile(context.TODO(), sess, bucket, key)
    if err != nil {
        log.WithFields(log.Fields{
            "err": err,
        }).Error("error downloading the file")
    }

    contents, err := ParseFile(file)
    if err != nil {
        log.WithFields(log.Fields{
            "err": err,
        }).Error("error parsing the file")
    }

    err = DeleteFile(file)
    if err != nil {
        log.WithFields(log.Fields{
            "err": err,
        }).Error("error deleting the file")
    }

    for _, c := range contents {
        log.WithFields(log.Fields{
            "record": c,
        }).Debug("printing the record")
    }
}

简而言之

  • 下载文件
  • 解析文件
  • 删除文件
  • 循环和打印输出

有用的提示

  1. 如今,我更多地使用了Vscode,我有点像Goland那样断奶。因此,您将在.vscode目录中找到一个launch.json文件。在那里您可以设置运行程序所需的环境变量
  2. 查看镶木木文件确实是我发现的痛苦。我喜欢的工具很少。在线观众会阻碍我的工作流程。但是我发现这个Vscode插件很棒。 Here is the link to the marketplace

包起来

希望您发现这很有帮助。就像我一开始提到的那样,文件作为数据介质而消失。当您处理较大的数据集时,Apache的镶木材料是一个很好的选择,这是您可以选择以DMS为输出的选项之一。

我继续只喜欢Golang的简单性和表现以及发展经验。 Parquet-go库有几个怪癖,但总的来说,我的5星级评级。