Mongodb Convention packs - c#

How does one use a MongoDB ConventionPack in C# I have the following code:
MongoDatabase Repository = Server.GetDatabase(RepoName);
this.Collection = Repository.GetCollection<T>(CollectionName);
var myConventions = new ConventionPack();
myConventions.Add(new CamelCaseElementNameConvention());
Does the convention pack automatically attach to this.Collection? When I load in a new object will it automatically persist it as this case? Do I have to add tags in my class declaration (like a data contract)?

You need to register the pack in the ConventionRegistry:
var pack = new ConventionPack();
pack.Add(new CamelCaseElementNameConvention());
ConventionRegistry.Register("camel case",
pack,
t => t.FullName.StartsWith("Your.Name.Space."));
If you want to apply this globally, you can replace the last param with something simpler like t => true.
Working sample code that serializes and de-serializes (driver 1.8.20, mongodb 2.5.0):
using System;
using System.Linq;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Driver;
namespace playground
{
class Simple
{
public ObjectId Id { get; set; }
public String Name { get; set; }
public int Counter { get; set; }
}
class Program
{
static void Main(string[] args)
{
MongoClient client = new MongoClient("mongodb://localhost/test");
var db = client.GetServer().GetDatabase("test");
var collection = db.GetCollection<Simple>("Simple");
var pack = new ConventionPack();
pack.Add(new CamelCaseElementNameConvention());
ConventionRegistry.Register("camel case", pack, t => true);
collection.Insert(new Simple { Counter = 1234, Name = "John" });
var all = collection.FindAll().ToList();
Console.WriteLine("Name: " + all[0].Name);
}
}
}

Related

C# Discord Bot prefix for commands doesn't work

I'm having a problem with my Discord Bot where the only method of interfacing with the bot is by tagging it in a message. I've setup the code for how I thought the prefix functionality was supposed to work, but I've done something wrong. I don't get any error messages when in use and the bot functions perfectly fine if its tagged, but doesn't react at all if you try to use the prefix instead. Can someone explain please? (I'm using DSharp for the discord api)
Here's the exact part of the code I think there's a problem with:
var commandsConfig = new CommandsNextConfiguration
{
StringPrefixes = new List<string>() { configJson.Prefix },
EnableDms = false,
EnableMentionPrefix = true,
DmHelp = false,
EnableDefaultHelp = true,
UseDefaultCommandHandler = true
};
Console.WriteLine($"HELLO! {configJson.Prefix}"); //Testing it could read the desired prefix (it can)
Commands = Client.UseCommandsNext(commandsConfig);
The configJson.cs looks like this:
public struct ConfigJson
{
[JsonProperty("token")]
public string Token { get; private set; }
[JsonProperty("prefix")]
public string Prefix { get; private set; }
}
The config.Json file looks like this (The token is removed for security)
{
"token": "#######",
"prefix": "!"
}
I'll also post the entire .cs if you want to recreate the conditions
using DSharpPlus;
using DSharpPlus.CommandsNext;
using DSharpPlus.EventArgs;
using DSharpPlus.Interactivity;
using DSharpPlus.Interactivity.Extensions;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using VLB.Commands.VLBCommands;
namespace VLB
{
public class Bot
{
public DiscordClient Client { get; private set; }
public InteractivityExtension Interactivity { get; private set; }
public CommandsNextExtension Commands { get; private set; }
public async Task RunAsync()
{
var json = string.Empty;
using (var fs = File.OpenRead("config.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = await sr.ReadToEndAsync().ConfigureAwait(false);
var configJson = JsonConvert.DeserializeObject<ConfigJson>(json);
var config = new DiscordConfiguration
{
Token = configJson.Token,
TokenType = TokenType.Bot,
AutoReconnect = true,
MinimumLogLevel = LogLevel.Debug,
};
Client = new DiscordClient(config);
Client.Ready += OnClientReady;
Client.UseInteractivity(new InteractivityConfiguration
{
Timeout = TimeSpan.FromSeconds(30)
});
var commandsConfig = new CommandsNextConfiguration
{
StringPrefixes = new List<string>() { configJson.Prefix },
EnableDms = false,
EnableMentionPrefix = true,
DmHelp = false,
EnableDefaultHelp = true,
UseDefaultCommandHandler = true
};
Console.WriteLine($"HELLO! {configJson.Prefix}"); //Testing it could read the desired prefix (it can)
Commands = Client.UseCommandsNext(commandsConfig);
Commands.RegisterCommands<VLBCommands>();
await Client.ConnectAsync();
await Task.Delay(-1);
}
private Task OnClientReady(DiscordClient client, ReadyEventArgs e)
{
return Task.CompletedTask;
}
}
}
I've tried changing the prefix to various conventional characters.
I've also tried changing the assignment to "StringPrefixes" to a string array instead of a list.
I'm only trying to use one prefix, but after scouring DSharp documentation I'm not sure CommandsNextConfiguration has a way to indicate only one prefix.
Thanks for reading :)

Mongodb How to Update many documents using C# driver

Please be so kind to help.
I got List of documents from xml parsing service and trying update it in DB.
I create fiter builder like .
var filter = Builders<T>.Filter.In("Id", List<T>);
and update builder like.
var update = Builders<T>.Update.Set("T.Property", List<T> )
and using UpdateManyAsync() updating documents in DB, but changings not apply.
How I could update documents in 1 step ?
Hello this is a sample using a .NET core 3.1 console application.
This is the csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.13.1" />
</ItemGroup>
</Project>
This is the code inside of the Program.cs file:
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MongoUpdateMany
{
public static class Program
{
public static async Task Main(string[] args)
{
const string databaseName = "test";
const string collectionName = "students";
var client = new MongoClient();
var database = client.GetDatabase(databaseName);
var collection = database.GetCollection<Student>(collectionName);
// just to be sure the test data are clean, nothing to do with the update sample
await database.DropCollectionAsync(collectionName).ConfigureAwait(false);
// create a bunch of students
var id = 1;
var enrico = new Student()
{
Name = "Enrico",
Id = id++,
IsActive = false
};
var luca = new Student
{
Name = "Luca",
Id = id++,
IsActive = false
};
var giulia = new Student
{
Name = "Giulia",
Id = id++,
IsActive = true
};
// fill the collection
await collection.InsertManyAsync(new List<Student> { enrico, giulia, luca }).ConfigureAwait(false);
// update many
var ids = new List<int> { enrico.Id, luca.Id };
var filter = Builders<Student>
.Filter
.In(x => x.Id, ids);
var update = Builders<Student>
.Update
.Set(x => x.IsActive, true);
await collection.UpdateManyAsync(filter, update).ConfigureAwait(false);
// verify updating the docs worked
await collection
.Find(student => ids.Contains(student.Id))
.ForEachAsync(student => Console.WriteLine($"Name: {student.Name} IsActive: {student.IsActive}"))
.ConfigureAwait(false);
Console.WriteLine();
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
}
public class Student
{
[BsonId]
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
}
Here is some useful links to learn how to use the official C# driver for mongodb:
driver documentation
free course from the Mongo university. I highly encourage you to take this course: courses available in the Mongo university catalog are of very high quality.

How can i update document in mongo db using .net(c#) driver without using Builders?

I am using MongoDb .net driver in which i have to update document based on certain condition.
Here is how my find query looks like in c# mongo driver
DbService.conversations.Find (new BsonDocument ("_id", new ObjectId ("obje-id-here"))).FirstOrDefault ();
How can i update specific field of document based on certain _id using Mongodb .net driver without using Builders?
**Note : **
I have tried this update query
var updateResultFromQuery = await DbService.conversations.UpdateOneAsync(Builders<RawBsonDocument>.Filter.Eq("_id", "5e01a89e5f317324780b7f83"),Builders<RawBsonDocument>.Update.Set("visitorName", "Guest41815"));
Console.WriteLine("after update response --- "+updateResultFromQuery.ToJson());
But it's not updating the value even i am receiving update response like this
{ "_t" : "Acknowledged" }
You could simply ReplaceOne object instead of updating it , that way you wont be forced to use builders but you will be doing a find and replace instead. 2 database operations instead of one. You can then update your object in memory instead.
Collection.ReplaceOne(filter, replacement, new UpdateOptions() { IsUpsert = false });
here's an example of create/update/find as requested:
using MongoDB.Entities; //Install-Package MongoDB.Entities
using MongoDB.Entities.Core;
using System;
using System.Linq;
namespace StackOverflow
{
public class Customer : Entity
{
public string Name { get; set; }
public Agent Agent { get; set; }
}
public class Agent
{
public string Name { get; set; }
public string Email { get; set; }
}
public class Program
{
private static void Main()
{
new DB("test", "localhost");
// create a customer with embedded agent
var customer = new Customer
{
Name = "Customer A",
Agent = new Agent { Name = "Agent Uno", Email = "uno#youknow.com" }
};
customer.Save();
// update customer name
DB.Update<Customer>()
.Match(c =>
c.ID == customer.ID &&
c.Agent.Email == "uno#youknow.com")
.Modify(c =>
c.Name, "Updated Customer")
.Execute();
// find updated customer
var cst = DB.Find<Customer>()
.Match(customer.ID)
.Execute()
.Single();
Console.WriteLine($"Customer Name: {cst.Name}");
Console.Read();
}
}
}
I achieved updating my document without using any third party library using these options
var filter = new BsonDocument(new Dictionary<string, dynamic> () {
{
"_id", new BsonObjectId("object-id-here")
},
{
"assigned_to.email" , agentEmail
}
});
var updateDoc = new BsonDocument(new Dictionary<string, dynamic> () {
{
"$set", new BsonDocument("assigned_to.$.avgResponseTime", Convert.ToDouble(obj.agentChatAvgResponseTime))
}
});
var updateQueryResult = DbService.conversations.UpdateOne(filter, updateDoc, new UpdateOptions {IsUpsert = false });

OpenNLP.Net inputStreamFactory : Error on attempt to load file

Hy,
I am pretty rookie to OpenNLP.Net and am a little bit lost on basic step.
I looked at some java code and try to convert it in C# but I think I am quite wrong given that I don't find any C# code
Right now I am trying to run this code located in the main
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using opennlp.tools.doccat;
using opennlp.tools.tokenize;
using opennlp.tools.util;
public class Account
{
public string Name { get; set; }
public string Email { get; set; }
public DateTime DOB { get; set; }
}
namespace Loading_OpenNLP
{
class Program
{
static void Main(string[] args)
{
Account account = new Account
{
Name = "John Doe",
Email = "john#microsoft.com",
DOB = new DateTime(1980, 2, 20, 0, 0, 0, DateTimeKind.Utc),
};
string json = JsonConvert.SerializeObject(account, Formatting.Indented);
Console.WriteLine(json);
getNLPModel();
string pause = Console.ReadLine();
}
static void getNLPModel()//java.io.File openNLPTraining)
{
InputStreamFactory inputStreamFactory = new MarkableFileInputStreamFactory(new java.io.File("D:\\text.txt"));
ObjectStream lineStream = new PlainTextByLineStream(inputStreamFactory, "UTF-8");
ObjectStream sampleStream = new DocumentSampleStream(lineStream);
}
}
}
It compiles but the File is not Found ... What's wrong?
You can implement InputStreamFactory by your own.
Here is F# sample that train custom NER model, InputStreamFactory is implemented using F# object expressions
open java.nio.charset
open java.io
#I "../packages/OpenNLP.NET/lib/"
#r "opennlp-tools-1.8.4.dll"
#r "opennlp-uima-1.8.4.dll"
open opennlp.tools.util
open opennlp.tools.namefind
let train (inputFile:string) =
let factory =
{ new InputStreamFactory with
member __.createInputStream () =
new FileInputStream(inputFile) :> InputStream }
let lineStream = new PlainTextByLineStream(factory, StandardCharsets.UTF_8)
use sampleStream = new NameSampleDataStream(lineStream)
let nameFinderFactory = new TokenNameFinderFactory()
let trainingParameters = new TrainingParameters();
//trainingParameters.put(TrainingParameters.ITERATIONS_PARAM, "5");
//trainingParameters.put(TrainingParameters.CUTOFF_PARAM, "200");
NameFinderME.train ("en", "person", sampleStream, trainingParameters, nameFinderFactory)
in C# the same code may look like this
using java.nio.charset;
using java.io;
using opennlp.tools.util;
using opennlp.tools.namefind;
namespace OpenNLP.Train
{
class MyStreamFactory: InputStreamFactory
{
public Factory(string fileName) => _filename = fileName;
private readonly string _filename;
public InputStream createInputStream()
=> new FileInputStream(_filename);
}
class Program
{
static void Main(string[] args)
{
var factory = new MyStreamFactory("D:\\text.txt");
var lineStream = new PlainTextByLineStream(factory, StandardCharsets.UTF_8);
var sampleStream = new NameSampleDataStream(lineStream);
var nameFinderFactory = new TokenNameFinderFactory();
var trainingParameters = new TrainingParameters();
var model = NameFinderME.train("en", "person", sampleStream, trainingParameters, nameFinderFactory);
}
}
}

Elastic Search to search for words that starts with phrase

I'm trying to create a search function for my website using Elastic Search and NEST. You can see my code below and I get results if I search for complete (and almost comlete) words.
Ie, if I search for "Buttermilk" or "Buttermil" I get a hit on my document containing the word "Buttermilk".
However, what I try to accomplish is if I search for "Butter", I should have a result with all three documents which have words that starts with "Butter". I thought this was solved by using FuzzyLikeThis?
Can anyone see what I'm doing wrong and point me in the right direction?
I created a console-app and the complete code you can see here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nest;
using Newtonsoft.Json;
namespace ElasticSearchTest
{
class Program
{
static void Main(string[] args)
{
var indexSettings = new IndexSettings();
indexSettings.Analysis.Analyzers["text-en"] = new SnowballAnalyzer { Language = "English" };
ElasticClient.CreateIndex("elastictesting", indexSettings);
var testItem1 = new TestItem {
Id = 1,
Name = "Buttermilk"
};
ElasticClient.Index(testItem1, "elastictesting", "TestItem", testItem1.Id);
var testItem2 = new TestItem {
Id = 2,
Name = "Buttercream"
};
ElasticClient.Index(testItem2, "elastictesting", "TestItem", testItem2.Id);
var testItem3 = new TestItem {
Id = 3,
Name = "Butternut"
};
ElasticClient.Index(testItem3, "elastictesting", "TestItem", testItem3.Id);
Console.WriteLine("Write search phrase:");
var searchPhrase = Console.ReadLine();
var searchResults = Search(searchPhrase);
Console.WriteLine("Number of search results: " + searchResults.Count());
foreach (var item in searchResults) {
Console.WriteLine(item.Name);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
private static List<TestItem> Search(string searchPhrase)
{
var query = BuildQuery(searchPhrase);
var result = ElasticClient
.Search(query)
.Documents
.Select(d => d)
.Distinct()
.ToList();
return result;
}
public static ElasticClient ElasticClient
{
get
{
var localhost = new Uri("http://localhost:9200");
var setting = new ConnectionSettings(localhost);
setting.SetDefaultIndex("elastictesting");
return new ElasticClient(setting);
}
}
private static SearchDescriptor<TestItem> BuildQuery(string searchPhrase)
{
var querifiedKeywords = string.Join(" AND ", searchPhrase.Split(' '));
var filters = new BaseFilter[1];
filters[0] = Filter<TestItem>.Bool(b => b.Should(m => m.Query(q =>
q.FuzzyLikeThis(flt =>
flt.OnFields(new[] {
"name"
}).LikeText(querifiedKeywords)
.PrefixLength(2)
.MaxQueryTerms(1)
.Boost(2))
)));
var searchDescriptor = new SearchDescriptor<TestItem>()
.Filter(f => f.Bool(b => b.Must(filters)))
.Index("elastictesting")
.Type("TestItem")
.Size(500);
var jsons = JsonConvert.SerializeObject(searchDescriptor, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
return searchDescriptor;
}
}
class TestItem {
public int Id { get; set; }
[ElasticProperty(Analyzer = "text-en", Index = FieldIndexOption.analyzed)]
public string Name { get; set; }
}
}
Edited 2014-04-01 11:18
Well, I ended up using MultiMatch and QueryString, so this it how my code looks now. Hope it mey help anyone in the furure. Also, I added a Description property to my TestItem to illustrate multimatch.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nest;
using Newtonsoft.Json;
namespace ElasticSearchTest
{
class Program
{
static void Main(string[] args)
{
var indexSettings = new IndexSettings();
ElasticClient.CreateIndex("elastictesting", indexSettings);
var testItem1 = new TestItem {
Id = 1,
Name = "Buttermilk",
Description = "butter with milk"
};
ElasticClient.Index(testItem1, "elastictesting", "TestItem", testItem1.Id);
var testItem2 = new TestItem {
Id = 2,
Name = "Buttercream",
Description = "Butter with cream"
};
ElasticClient.Index(testItem2, "elastictesting", "TestItem", testItem2.Id);
var testItem3 = new TestItem {
Id = 3,
Name = "Butternut",
Description = "Butter with nut"
};
ElasticClient.Index(testItem3, "elastictesting", "TestItem", testItem3.Id);
Console.WriteLine("Write search phrase:");
var searchPhrase = Console.ReadLine();
var searchResults = Search(searchPhrase);
Console.WriteLine("Number of search results: " + searchResults.Count());
foreach (var item in searchResults) {
Console.WriteLine(item.Name);
Console.WriteLine(item.Description);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
private static List<TestItem> Search(string searchPhrase)
{
var query = BuildQuery(searchPhrase);
var result = ElasticClient
.Search(query)
.Documents
.Select(d => d)
.Distinct()
.ToList();
return result;
}
public static ElasticClient ElasticClient
{
get
{
var localhost = new Uri("http://localhost:9200");
var setting = new ConnectionSettings(localhost);
setting.SetDefaultIndex("elastictesting");
return new ElasticClient(setting);
}
}
private static SearchDescriptor<TestItem> BuildQuery(string searchPhrase)
{
var searchDescriptor = new SearchDescriptor<TestItem>()
.Query(q => q
.MultiMatch(m =>
m.OnFields(new[] {
"name",
"description"
}).QueryString(searchPhrase).Type(TextQueryType.PHRASE_PREFIX)
)
)
.Index("elastictesting")
.Type("TestItem")
.Size(500);
var jsons = JsonConvert.SerializeObject(searchDescriptor, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
return searchDescriptor;
}
}
class TestItem {
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
Instead of using FuzzyLikequery.. use prefix query its more fast and accurate..!
for more information refer
curl -XPOST "http://localhost:9200/try/indextype/_search" -d'
{
"query": {
"prefix": {
"field": {
"value": "Butter"
}
}
}
}'
create above query in NEST and try again..!
This has nothing to do with FuzzyLikeThis.
You can use prefixquery as suggested by #BlackPOP out of the box.
You could also opt for using EdgeNGrams, this will tokenize your input on index-time. The result faster performance as compared to prefixquery, offset against increased index size.
One thing to keep in mind is that prefixquery only works on non-analyzed fields, so if you want to do any anaylzing at indexing-time, you're probably better off using EdgeNGrams.
Please read up on anaylzers etc, if you don't know what they are.
Some refs:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-analyzers.html
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-edgengram-tokenizer.html
See How can I do a prefix search in ElasticSearch in addition to a generic query string? for a similar question.

Categories

Resources