使用PowerShell

时间:2018-04-27 00:56:00

标签: mongodb powershell

我有一个PowerShell脚本,一直让我感到烦恼。我终于到了可以获得收藏的地步,但是我收到了一个我无法弄清楚的错误。

function Get-MongoDBCollection {
  Param(
    $database,
    $CollectionName,
    $settings = $null, #[MongoDB.Driver.MongoCollectionSetting]
    $returnType = [PSOBJECT]
  )
  $method = $database.GetType().GetMethod('GetCollection')
  $gericMethod = $method.MakeGenericMethod($returnType)
  $gericMethod.Invoke($database,[object[]]($CollectionName,$settings))
}

$dbName = "MyDatabaseName"
$collectionName = "MyCollectionName"

try {
   add-type -path 'C:\Program Files\MongoDB\Drivers\System.Runtime.InteropServices.RuntimeInformation.4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll'
  Add-Type -Path "C:\Program Files\MongoDB\Drivers\MongoDB.Bson.2.6.0\lib\net45\MongoDB.Bson.dll"

   add-type -path "C:\Program Files\MongoDB\Drivers\DnsClient.1.0.7\lib\net45\DnsClient.dll";
   Add-Type -path "C:\Program Files\MongoDB\Drivers\MongoDB.Driver.Core.2.6.0\lib\net45\MongoDb.Driver.Core.dll"
   Add-Type -Path "C:\Program Files\MongoDB\Drivers\MongoDB.Driver.2.6.0\lib\net45\MongoDB.Driver.dll"
}
catch {
  $_;
  $_.Exception.LoaderExceptions

}

$connectionString = "mongodb://localhost:27018";
$mongoClient = new-object MongoDb.Driver.MongoClient($connectionString);

$mongoDatabase = $mongoclient.GetDatabase($dbName)
$mongoDatabase.GetCollection($collectionname)

$collection = Get-MongoDBCollection $mongodatabase "SharePoint" -returnType ([MongoDB.Bson.BsonDocument]);

$datafile = Get-Content -Raw -Path "D:\datafiles\86fba866-77ed-4f40-4637-08d57d2e25b4.json" #`| ConvertFrom-Json
[MongoDB.Bson.BsonDocument] $doc = [MongoDB.Bson.BsonDocument]::Parse($datafile);
$x = $collection.InsertOne($doc)

该脚本获取文件的内容,该文件包含JSON字符串并将其转换为BsonDocument,然后尝试插入它。我收到以下错误。

Argument types do not match
At line:1 char:1
+ $collection.InsertOneAsync($doc)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  + CategoryInfo          : OperationStopped: (:) [], ArgumentException
  + FullyQualifiedErrorId : System.ArgumentException

我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

这是一个艰难的饼干!基本上,powershell不会以微不足道的方式支持泛型。它支持它们,但是以复杂且难以理解的方式支持它们!

我在几天前在另一个堆栈溢出中发现了这个片段,但此时无法找到它。开始时这是一个令人不愉快的搜索/跋涉。我希望我可以给予适当信用的原作者的片段如下:

###
# Usage:
# $Collection = Get-MongoDBCollection $database 'collectionName'
#  or
# $Collection = Get-MongoDBCollection $database 'collectionName' -returnType  ([MongoDB.Bson.BsonDocument])
function Get-MongoDBCollection {
   Param(
    $database,
    $CollectionName,
    $settings = $null, #[MongoDB.Driver.MongoCollectionSetting]
    $returnType = [PSOBJECT]
  )
  $method = $database.GetType().GetMethod('GetCollection')
  $gericMethod = $method.MakeGenericMethod($returnType)
  $gericMethod.Invoke($database,[object[]]($CollectionName,$settings))
}

以下是我在下面的完整上下文用法。我还必须自己加载DnsClient.dll依赖项。在整个过程中,通常情况下,powershell模块无法提供有用的错误。

PS:这是业余的powershell,只使用.ps因为我需要连接Office365!没有最佳实践的承诺!

#########
# Globals
##

$mongoDbDriverPath = "Z:\Work\mb-rule-watch\lib\net45"
$dbName = "mbRules"
$collectionName = "Mailboxes"

#########
# Load o365 credentials/modules
##

  Import-Module MsOnline

  if( ! $credential ){
     Write-Host "Requesting Credentials - Use o365 Admin Account"
     $credential = Get-Credential
     Connect-MsolService -Credential $credential
  }

  # Prep remote session connection
  if( ! $session ){
     $session = New-PSSession `
        -ConfigurationName Microsoft.Exchange `
        -ConnectionUri https://outlook.office365.com/powershell-liveid/ `
        -Credential $credential `
        -Authentication Basic `
        -AllowRedirection

     # import commands from Microsoft Exchange Server shell
     Import-PSSession $session
  }

###########
# Functions
##

  ###
  # Usage:
  # $Collection = Get-MongoDBCollection $database 'collectionName'
  #  or
  # $Collection = Get-MongoDBCollection $database 'collectionName' -returnType  ([MongoDB.Bson.BsonDocument])
  function Get-MongoDBCollection {
    Param(
        $database,
        $CollectionName,
        $settings = $null, #[MongoDB.Driver.MongoCollectionSetting]
        $returnType = [PSOBJECT]
    )
    $method = $database.GetType().GetMethod('GetCollection')
    $gericMethod = $method.MakeGenericMethod($returnType)
    $gericMethod.Invoke($database,[object[]]($CollectionName,$settings))
  }

###########
# MAIN
##
try
{
  # Load mongo driver
  Add-Type -Path "$($mongoDbDriverPath)\DnsClient.dll"
  Add-Type -Path "$($mongoDbDriverPath)\MongoDB.Bson.dll"
  Add-Type -Path "$($mongoDbDriverPath)\MongoDB.Driver.Core.dll"
  Add-Type -Path "$($mongoDbDriverPath)\MongoDB.Driver.dll"

  # Connect to mongo
  $client = new-object -TypeName MongoDB.Driver.MongoClient -ArgumentList "mongodb://localhost"

  # Get DB handle
  [MongoDB.Driver.IMongoDatabase] $db = $client.GetDatabase( $dbName );

  # Aquire Collection handle with brute force generic hacks Via a PS god on stackoverflow.
  $collection = Get-MongoDBCollection $db $collectionName -returnType ([MongoDB.Bson.BsonDocument])

  #foreach( $mbx in $( Get-Mailbox -ResultSize Unlimited -identity example_user_id ) ){
  foreach( $mbx in $( Get-Mailbox -ResultSize Unlimited ) ){

    $identityStr = $mbx.identity

    $rules =  Get-InboxRule -Mailbox $identityStr

    # convert some huge ints (>Mongo Int64) to strings
    foreach( $rule in $rules ){
      $rule.RuleIdentity = "" + $rule.RuleIdentity + ""
    }

    # Json Stringify
    $rules_json = ConvertTo-Json $rules

    # If the mailbox had rules
    if( $rules_json ){

      write-host( "Inserting rules for: " + $identityStr )

      # Cache results to FS this time.
      echo $rules_json > var\rules\$identityStr.rules.json

      try{

        # Type convert/parse our json string
        $document = new-object -TypeName MongoDB.Bson.BsonDocument
        $document = [MongoDb.Bson.BsonDocument]::Parse( '{ "_username":"' + $identityStr + '","rules": ' + $rules_json + '}' );

        # Insert the JSON document
        $collection.InsertOne( $document )

      } catch {

        Write-Host "JSON parse or mongo insert failure"

        foreach( $x IN $_.Exception ){
          foreach( $msg IN $x ){
            Write-Error $msg
          }
        }

      }
    }
  }
}
catch
{
  Write-Host "Script errors occured"
  if( $_.Exception.LoaderExceptions ){
    Write-Host "!!Dependency Loads Failed!!"
    foreach( $msg IN $_.Exception.LoaderExceptions ){
      Write-Error $msg
    }
  } else {
    foreach( $x IN $_.Exception ){
      foreach( $msg IN $x ){
        Write-Error $msg
      }
    }
  }
}