MongoDataApi for dotnet.

Answered
Eric Morgan asked on March 20, 2023

Hi, I want to integrate(embed) mongo DB into our server. But as I understand there is no API for dotnet, right?
 
I saw that it is possible to do with node.js server.
https://www.flexmonster.com/doc/embed-mongodb-connector/
Do you have any suggestion how I can solve this on dotnet side?
BTW, here is my solution for other SQL Database Providers. It works perfect and I wanted to add NoSQL database support to here:

[Route("api/analytic-service/fm-reports")]
public class FmReportsController : AnalyticServiceController, IFmReportsAppService
{
private readonly IFmReportsAppService _fmReportsAppService;
private readonly IApiService _fmApiService;
private readonly IDataSourcesAppService _dataSourcesAppService;
private readonly IDataStorage _dataStorage;
private readonly IJsonSerializer _jsonSerializer;
private readonly IOptionsMonitor<DatasourceOptions> _datasourceOptions;
private readonly IDatabaseConnectorsAppService _databaseConnectorsAppService;

public FmReportsController(
IFmReportsAppService fmReportsAppService,
IApiService fmApiService,
IOptionsMonitor<DatasourceOptions> datasourceOptions,
IDataSourcesAppService dataSourcesAppService,
IDataStorage dataStorage,
IJsonSerializer jsonSerializer,
IDatabaseConnectorsAppService databaseConnectorsAppService
)
{
_fmReportsAppService = fmReportsAppService;
_fmApiService = fmApiService;
_dataSourcesAppService = dataSourcesAppService;
_dataStorage = dataStorage;
_jsonSerializer = jsonSerializer;
_databaseConnectorsAppService = databaseConnectorsAppService;
_datasourceOptions = datasourceOptions;
}

[HttpPost("initialize-index/{id}")]
public async Task InitializeIndexAsync(Guid id)
{
var entityDto = await _dataSourcesAppService.GetAsync(id);
var dbConnector = await _databaseConnectorsAppService.GetAsync(entityDto.ConnectorId);
if (_datasourceOptions.CurrentValue.Indexes.All(x => x.Key != entityDto.Id.ToString()))
{
// TODO: I want to add NoSQL databases support
_datasourceOptions.CurrentValue.Indexes.Add(entityDto.Id.ToString(), new DatabaseIndexOptions
{
Type = ConnectorTypes.Database.ToDescription().ToLower(),
Query = dbConnector.Query,
ConnectionString = dbConnector.ConnectionString,
DatabaseType = dbConnector.DatabaseProvider.ToDescription()
});
await _dataStorage.GetOrAddAsync(id.ToString());
}
}

[HttpPost("handshake")]
public Task<HandshakeResponse> HandshakeAsync()
{
return _fmReportsAppService.HandshakeAsync();
}

[HttpPost("fields")]
public Task<Schema> PostFieldsAsync(FieldsRequest request)
{
return _fmApiService.GetFieldsAsync(request.Index);
}

[HttpPost("members")]
public Task<MembersResponse> PostMembersAsync(MembersRequest request)
{
return _fmApiService.GetMembersAsync(request);
}

[HttpPost("select")]
public async Task<SelectResponse> PostSelectAsync()
{
var request = HttpContext.Request;
var stream = new StreamReader(request.Body);
var body = await stream.ReadToEndAsync();
var selectRequest = _jsonSerializer.Deserialize<SelectRequest>(body);

return await _fmApiService.GetAggregatedDataAsync(selectRequest);
}
}

And client:

let report = {
dataSource: {
type: "api",
url: this.environment.getEnvironment().apis.AnalyticService.fmDataSourceUrl + '/api/analytic-service/fm-reports',
index: this.selected.dataSourceId
}
};

pivot.setReport(report);

5 answers

Public
Solomiia Andrusiv Solomiia Andrusiv Flexmonster March 22, 2023

Hello, Patrick!
 
Hope you are doing well.
 
Kindly note that we can suggest the MongoDB connector out of the box only for Node.js servers. 
 
However, it seems that you are using Flexmonster Data Server as a DLL in your project. 
If so, it is possible to implement a custom parser for connecting to MongoDB by following our guide: https://www.flexmonster.com/doc/implementing-custom-parser/.
 
Please let us know if the suggested approach works for your case.
 
Looking forward to hearing from you.
 
Regards,
Solomiia

Public
Eric Morgan March 22, 2023

Hi Solomiia, yes we are using Flexmonster Data Server as a DLL. I will try what you suggested and will inform you. Thanks.

Public
Solomiia Andrusiv Solomiia Andrusiv Flexmonster March 23, 2023

Hello, Patrick!

Thank you for getting back to us.

We'll be waiting for the following updates on the case.

Feel free to contact us if any other questions arise.

Kind regards,
Solomiia

Public
Eric Morgan March 24, 2023

Hi Solomiia, I created custom parser like you suggested and it is working perfectly. Thanks.

Let me share my implementation that can help to others.

Here is the my MongoDbParser:

public class MongoDbParser : IParser
{
private readonly DataReaderFactory _dataReaderFactory;

public MongoDbParser(DataReaderFactory dataReaderFactory)
{
Type = DatabaseProviderTypes.MongoDb.ToDescription();
_dataReaderFactory = dataReaderFactory;
}

public string Type { get; set; }
public IndexOptions IndexOptions { get; set; }
public Dictionary<int, ColumnInfo> ColumnInfoByIndex { get; set; }

public IEnumerable<object[,]> Parse()
{
ColumnInfoByIndex = new Dictionary<int, ColumnInfo>();

var indexOptions = IndexOptions as MongoDbIndexOptions ?? throw new Exception("IndexOptions is not MongoDbIndexOptions");
var readerResult = _dataReaderFactory.Create(ConnectorTypes.Database).ReadAsync(new DataReaderInput
{
DatabaseDataReaderInput = new DatabaseDataReaderInput
{
ConnectionString = indexOptions.ConnectionString,
Query = indexOptions.Query,
DatabaseProvider = EnumExtensions.ToEnum<DatabaseProviderTypes>(indexOptions.DatabaseType)
}
}).Result;

var list = readerResult[0].Rows as List<Dictionary<string, object>>;
var totalColumnCount = list.Max(x => x.Count);
var firstRow = list.FirstOrDefault(x => x.Count == totalColumnCount);
var columnIndex = 0;
foreach (var column in firstRow)
{
ColumnInfoByIndex.Add(columnIndex, new ColumnInfo(column.Key, column.Value.GetType()));
columnIndex++;
}

var dataBlock = new object[list.Count, totalColumnCount];
var i = 0;
foreach (var row in list)
{
var j = 0;
foreach (var column in row)
{
dataBlock[i, j] = column.Value;
j++;
}

i++;
}

yield return dataBlock;
}
}

And here is the MongoDbIndexOptions:

public class MongoDbIndexOptions : IndexOptions
{
public string Query { get; set; }

public string DatabaseType { get; set; }

public string ConnectionString { get; set; }

public MongoDbIndexOptions() : base(DatabaseProviderTypes.MongoDb.ToDescription())
{
}

public MongoDbIndexOptions(string databaseType, string connectionString, string query) : base(DatabaseProviderTypes.MongoDb.ToDescription())
{
ConnectionString = connectionString;
DatabaseType = databaseType;
Query = query;
}
}
Public
Nadia Khodakivska Nadia Khodakivska Flexmonster March 27, 2023

Hello, Patrick!

Thank you for your feedback and for sharing your implementation on Help Center.

We are glad to hear that everything works perfectly for you.

Feel free to contact us in case of any other questions.

Regards,
Nadia

Please login or Register to Submit Answer