I do not understand how to add recording parameters for MongoDB using mongo-go-driver
Example request
c.client.Database(MONGO_DATABASE).Collection(*packet.ID).InsertMany(nil, packet.Item, opt)
How to specify the necessary parameters in opt?
VERSION 1.0
In MongoDB Go driver production release you can set writeConcern as below:
import (
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
mongoURI := "mongodb://server:port/"
opts := options.Client().ApplyURI(mongoURI).SetWriteConcern(writeconcern.New(writeconcern.WMajority()))
client, err := mongo.NewClient(opts)
if err != nil {
panic(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
err = client.Connect(ctx)
if err != nil {
panic(err)
}
collection := client.Database("database").Collection("collection")
See also:
mongo-driver/mongo/options
mongo-driver/mongo/writeconcern
VERSION 0.0.16
Using mongo-go-driver, you can set a write concern option as below example:
import(
"github.com/mongodb/mongo-go-driver/bson"
"github.com/mongodb/mongo-go-driver/core/writeconcern"
"github.com/mongodb/mongo-go-driver/mongo"
"github.com/mongodb/mongo-go-driver/mongo/collectionopt"
)
// Example document
document := bson.VC.DocumentFromElements(
bson.EC.SubDocumentFromElements(
"foo",
bson.EC.Int32("bar", 101),
),
)
// Set majority write concern
wMajority := writeconcern.New(writeconcern.WMajority())
database := client.Database("database")
collection := database.Collection("collection", collectionopt.WriteConcern(wMajority))
_, err = collection.InsertOne(context.Background(), document)
Can also use W(int) to specify an arbitrary number of mongod instances. See more writeconcern/writeconcern.go
Related
I need help understanding this error. The code works with sqlite. The ? looks like the sql package is not even putting a value there but sending the question mark as is.
I can run other select statements without issues so its not a connection problem or something like that.
Error: Incorrect syntax near '?'
func TestSQLServerInsert(t *testing.T) {
db, err := sql.Open("sqlserver", "my_trusted_string")
//db, err := sql.Open("sqlite3", "../data/utm_info.db")
if err != nil {
t.Errorf("could not open database: %v", err)
}
defer db.Close()
c := controller.NewC(db)
u := controller.UtilizationResponse{
Snapshot: []int{46, 22, 4, 4, 5, 3, 0, 8, 49},
History: []float32{55.1, 47.2, 0.3, 33.4, 23.5},
Time: time.Now(),
}
affectedRows, err := c.InsertUtil(u)
if err != nil {
t.Errorf("could not insert into db: %v", err)
}
var count int64 = 1
assert.Equal(t, affectedRows, count)
}
// InsertUtil response inserts a new record into the database
func (c *Controller) InsertUtil(u UtilizationResponse) (rowsAffected int64, err error) {
return insertUtil(c.DB, u)
}
func insertUtil(db *sql.DB, u UtilizationResponse) (int64, error) {
stmt, err := db.Prepare("INSERT INTO Utilization VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")
if err != nil {
return 0, err
}
res, err := stmt.Exec(
u.Time,
u.Snapshot[0],
u.Snapshot[1],
u.Snapshot[2],
u.Snapshot[3],
u.Snapshot[4],
u.Snapshot[5],
u.Snapshot[6],
u.Snapshot[7],
u.Snapshot[8],
u.History[0],
u.History[1],
u.History[2],
u.History[3],
u.History[4],
)
if err != nil {
return 0, err
}
rowCnt, err := res.RowsAffected()
if err != nil {
return 0, err
}
return rowCnt, nil
}
type UtilizationResponse struct {
Snapshot []int `json:"snapshot,omitempty"`
History []float32 `json:"history,omitempty"`
Time time.Time `json:"time,omitempty"`
}
The sqlserver driver uses normal MS SQL Server syntax and expects parameters in the sql query to be in the form of either #Name or #p1 to #pN (ordinal position).
insertSql := "insert into test (id, idstr) values (#p1, #p2)"
After some testing, I can confirm it works. It even works with sqlite3 so this seems to be a more widely accepted way.
I am contemplating the migration from Advantage Native Delphi components to FireDAC. I have been searching for a way to determine how with FireDAC I can determine the method that was used to connect to the server - Remote, Local, AIS (Internet).
I would be looking for the equivalent of TAdsConnection.ConnectionType.
Thanks
Gary Conley
The function you're looking for is called AdsGetConnectionType. Its import you can find declared in the FireDAC.Phys.ADSCli module, but it's not used anywhere.
But it's not so difficult to get its address and call it by yourself. For example (not a good one):
uses
FireDAC.Stan.Consts, FireDAC.Phys.ADSCli, FireDAC.Phys.ADSWrapper;
var
FTAdsGetConnectionType: TAdsGetConnectionType = nil;
type
TADSLib = class(FireDAC.Phys.ADSWrapper.TADSLib)
end;
function GetConnectionType(Connection: TFDConnection): Word;
const
AdsGetConnectionTypeName = 'AdsGetConnectionType';
var
CliLib: TADSLib;
CliCon: TADSConnection;
Status: UNSIGNED32;
Output: UNSIGNED16;
begin
Result := 0;
CliCon := TADSConnection(Connection.CliObj);
CliLib := TADSLib(CliCon.Lib);
if not Assigned(FTAdsGetConnectionType) then
FTAdsGetConnectionType := CliLib.GetProc(AdsGetConnectionTypeName);
if Assigned(FTAdsGetConnectionType) then
begin
Status := FTAdsGetConnectionType(CliCon.Handle, #Output);
if Status = AE_SUCCESS then
Result := Word(Output)
else
FDException(CliLib.OwningObj, EADSNativeException.Create(Status, CliLib, nil),
{$IFDEF FireDAC_Monitor}True{$ELSE}False{$ENDIF});
end
else
FDException(CliLib.OwningObj, [S_FD_LPhys, CliLib.DriverID],
er_FD_AccCantGetLibraryEntry, [AdsGetConnectionTypeName]);
end;
Possible usage:
case GetConnectionType(FDConnection1) of
ADS_AIS_SERVER: ShowMessage('AIS server');
ADS_LOCAL_SERVER: ShowMessage('Local server');
ADS_REMOTE_SERVER: ShowMessage('Remove server');
end;
I'm having issues setting the timeout in go-mssqldb
This is my current connection string:
sqlserver://user:password#server?timeout=1m30s
I can connect just fine, run queries etc. but I keep timing out at the default value of 30 seconds.
I'm referencing the documentation here.
What am I missing?
import (
"database/sql"
_ "github.com/denisenkom/go-mssqldb"
)
func main(){
db, err := sql.Open("mssql", "sqlserver://user:password#server?timeout=1m30s")
if err != nil{
panic(err)
}
_, err = db.Exec("run query that takes longer than 30 seconds")
if err != nil{
panic(err)
}
// panic at 30 seconds...
// panic: read tcp {my ip}->{server ip}: i/o timeout
}
I was referencing the wrong documentation initially. To format the url see the following:
"sqlserver://user:password#server?connection+timeout=90"
Iteration to datastore query result in GAE/Go is very slow.
q := datastore.NewQuery("MyStruct")
gaeLog.Infof(ctx, "run") // (1)
it := client.Run(ctx, q)
list := make([]MyStruct, 0, 10000)
gaeLog.Infof(ctx, "start mapping") // (2)
for {
var m MyStruct
_, err := it.Next(&m)
if err == iterator.Done {
break
}
if err != nil {
gaeLog.Errorf(ctx, "datastore read error : %s ", err.Error())
<some error handling>
break
}
list = append(list , m)
}
gaeLog.Infof(ctx, "end mapping. count : %d", len(list)) // (3)
The result is below.
18:02:11.283 run // (1)
18:02:11.291 start mapping // (2)
18:02:15.741 end mapping. count : 2400 // (3)
It takes about 4.5 seconds between (2) and (3), just only 2400 record. It is very slow.
How can I improve performance?
[Update]
I added the query in above code q := datastore.NewQuery("MyStruct").
I tried to retrieve all the entities in the kind MyStruct. This kind has 2400 entities.
I was using cloud.google.com/go/datastore and found it is slow. I migrated to use google.golang.org/appengine/datastore.
The result is as follows, less than 1 second.
13:57:46.216 run
13:57:46.367 start mapping
13:57:47.063 end mapping. count : 2400
I am uploading a file via the following code.
After a successful upload I am attempting to Delete the file but I am getting a 32 - File in use error.
Can anyone tell me how I can resolve this file in use error? The following code is uploading the file, but not releasing it when done..
var
HTTP: TidHTTP;
SSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
PostData: TIdMultiPartFormDataStream;
ResponseStream: TStringStream;
Delete : Boolean;
begin
ResponseStream := TStringStream.Create('');
HTTP := TidHTTP.Create(nil);
SSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
SSLIOHandler.SSLOptions.Method := sslvSSLv3;
HTTP.ReadTimeout := 30000; //30 seconds
HTTP.ConnectTimeout := 30000; //30 seconds
HTTP.IOHandler := SSLIOHandler;
HTTP.HTTPOptions := [hoKeepOrigProtocol];
HTTP.ProtocolVersion := pv1_1;
PostData := TIdMultiPartFormDataStream.Create;
PostData.AddFormField('username', 'demo');
PostData.AddFormField('password', 'demo');
PostData.AddFormField('action', 'upload');
PostData.AddFormField('accountno', 'demo');
PostData.AddFile('uploadedfile', FileName, GetMIMETypeFromFile(FileName));
HTTP.Request.ContentType := PostData.RequestContentType;
HTTP.Post('http://uploadsite.com/ex/exampleAPI.asmx/Process', PostData, ResponseStream);
if AnsiContainsStr(ResponseStream.DataString, 'Done') then
Delete := True;
finally
SSLIOHandler.Free;
HTTP.Free;
ResponseStream.Free;
end;
if Delete then
if DeleteFile(BFlashFileName) then
ShowMessage('Deleted')
else ShowMessage(BFlashFileName+' not deleted, error = '+
IntToStr(GetLastError));
Call the Clear method of your TIdMultiPartFormDataStream instance before attempting to delete the file. If you don't need it anymore, freeing it will also amount to same (i.e. PostData.Free). Currently, it looks like you're leaking your PostData variable.
While TIdMultiPartFormDataStream is clearing its Fields collection, the file stream created by the AddFile method will be destroyed closing the file's handle.