I have this script that pulls text out of .docx, .doc and .pdf files and uploads that text to an Azure SQL Server. This is so users can search on the contents of those documents without using Windows Search / Azure Search.
The filenames are all in the following format:
firstname surname - id.extension
The id is incorrect though, the ID is from an outdated database and the new database that I am updating holds both (newID and oldID).
COLUMNS:
- ID - New ID of the candidate record
- OldID - Old ID of the candidate record (old database schema)
- OriginalResumeID - Document link ID for the candidate table to the document table
- CachedText - The field I am updating (holds the document text) at the moment this will mostly be NULL
Here is the script:
## Get resume list
$params = @{
'Database' = $TRIS5DATABASENAME
'ServerInstance' = $($AzureServerInstance.FullyQualifiedDomainName)
'Username' = $AdminLogin
'Password' = $InsecurePassword
'query' = "SELECT id, OldID, OriginalResumeID FROM Candidate WHERE OriginalResumeID IS NOT NULL"
}
$IDCheck = Invoke-Sqlcmd @params
## Word object
$files = Get-ChildItem -force -recurse $documentFolder -include *.doc, *.pdf, *.docx
$word = New-Object -ComObject word.application
$word.Visible = $false
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatText")
foreach ($file in $files) {
Write-Output "Processing: $($file.FullName)"
$doc = $word.Documents.Open($file.FullName)
$fileName = $file.BaseName + '.txt'
$doc.SaveAs("$env:TEMP\$fileName", [ref]$saveFormat)
Write-Output "File saved as $env:TEMP\$fileName"
$doc.Close()
$4ID = $fileName.split('-')[1].replace(' ', '').replace(".txt", "")
$text = Get-Content "$env:TEMP\$fileName"
$text = $text.replace("'", "''")
$resumeID = $IDCheck | where {$_.OldID -eq $4id} | Select-Object OriginalResumeID
$resumeID = $resumeID.OriginalResumeID
<# Upload to azure #>
$params = @{
'Database' = $TRIS5DATABASENAME
'ServerInstance' = $($AzureServerInstance.FullyQualifiedDomainName)
'Username' = $AdminLogin
'Password' = $InsecurePassword
'query' = "Update Document SET CachedText = '$text' WHERE id = $ResumeID"
}
Invoke-Sqlcmd @params -ErrorAction "SilentlyContinue"
Remove-Item -Force "$env:TEMP\$fileName"
}
$word.Quit()
The problem is that running this on a large dataset, let's say 750000 documents takes far too long per document. I'm fairly certain that this is because it has to search through the entire $IDCheck object of 750000 records before it can get the originalResumeID of the record to upload to.
Running this on a smaller database is quite quick (around 200000 per 24 hours). I was thinking I could check the documents table and only pull rows where the CachedText field is null and loop that to run every 50000 documents so it would get quicker as it goes. Problem is the documents table will be massive and will take a long time to search through every time this is called.
Any help on speeding this up would be much appreciated.
EDIT:
Looks like it is the upload to azure causing the delay:
<# Upload to azure #>
$params = @{
'Database' = $TRIS5DATABASENAME
'ServerInstance' = $($AzureServerInstance.FullyQualifiedDomainName)
'Username' = $AdminLogin
'Password' = $InsecurePassword
'query' = "Update Document SET CachedText = '$text' WHERE id = $ResumeID"
}
Invoke-Sqlcmd @params -ErrorAction "SilentlyContinue"
Get-Content
is super slow too. Use-raw
parameter to get the text as a string. \$\endgroup\$