How to change the default analyzer for dynamic fields - ravendb

RavenDB uses the LowerCaseKeywordAnalyzer by default and switches (if I'm not mistaken) to the StandardAnalyzer if you set a field to FieldIndexing.Analyzed.
RavenDB also defaults to the LowerCaseKeywordAnalyzer for dynamic fields.
I would like to change this. I want RavenDB to use the StandardAnalyzer for ALL my dynamic fields.
How can I do that?
Do I have to use a plugin and implement AbstractAnalyzerGenerator?
I would prefer not to since this will make deployment a lot more complicated for something as simple as changing the default analyzer.

I fixed this problem with the next code.
public class Product_ByFields : AbstractIndexCreationTask<Product>
{
public Product_ByFields()
{
Map = products => from product in products
select new
{
_ = product.FieldValues.Select(f => CreateField(f.Key, f.Value.SearchTerms, false, true))
};
this.Analyze("__all_fields", "Lucene.Net.Analysis.Standard.StandardAnalyzer");
}
}

You can use this:
_= CreateField("Foo", "bar", stored: false, analyzed: true);

Related

HotChocolate: Dynamic schemas and how to update filters accordingly

NOTE: If you do know that the below is not possible, this information is just as valuable.
Im checking out HotChocolate and Ive looked into the dynamic schemas
I have taken the code in your Github-example This works ok. I have extended our Product-type like so:
//Same json as in your Github-sample, new properties are "color" and some more
foreach (var field in type.GetProperty("fields").EnumerateArray())
{
string name = field.GetString();
typeDefinition.Fields.Add(new ObjectFieldDefinition(field.GetString()!, type: TypeReference.Parse("String"), pureResolver: ctx =>
{
var product = ctx.Parent<Product>();
return product.SubTypeSpecific.ContainsKey(name) ? product.SubTypeSpecific[name] : null;
}));
}
now I have "moved out" dynamic properties from a Dictionary (That is a sub-object in my documentDb) to own properties. Works well.
BUT:
How can I extend my ProductFilter in the same fashion?
I would like to extend my current Product-filter so its possible to search on the new dynamic property "color"
getProducts(where : color : {eq :"blue" }}) {...}
I can create new FilterInputDefinition, but not extend existing filter (because there is no FilterInputTypeExtensions.CreateUnsafe()
If I manage to create the new filter, is there any way to update the IQueryable-generation so that the inputed color ("blue")
So the query to my CosmosDb will be created automatically?
Many thanks in advance.

How to call mongodb server function inside update statement

Lets say there is an array defined as sub document.
User
first_name:"blah",
last_name: "blah",
scores [{score: 12},
{score: 13},
{score: 9},
{score: 14}]
Say I want to loop through this sub array inside the update statement and check if I need to add a new score. New score could be 8 or 16 if its 8 then nothing should be added, however if its 16 it should be added to the end of the list.
Is there is anyway to define javascript server side function and use it inside update statement, or there are other way of doing something like that? The important thing that operation has to be atomic.
Using php driver
public bool|array MongoCollection::update ( array $criteria , array $new_object [, array $options = array() ] )
How do I specify criteria to match those conditions that I have listed?
You can create a server-side javascript function, however the creators of mongo do not recommend this:
We do not recommend using server-side stored functions if possible.
If you need atomicity with complex logic, one approach with is to lock the document before working with it. You can achieve this with the findAndModify function. The basic gist of this is that you try to find your document as you normally would, with the additional criteria that locked = false. The modify part of this function would set locked = true.
db.people.findAndModify({
query: { name: "Andy", locked: false },
update: { locked: true },
});
You now are free to work with the document "atomically" When you write the changes back to your database, you set locked = false. Make sure you wrap your block in a try/catch/finally and ensure the document is unlocked in the finally block.
Note that if your operation is very simple (simply need to add a field to your list), then using findAndModify alone to update the document fields may be enough for what you need.
Edit: If you really want to use server-side functions here's an example from the PHP mongo documentation:
$response = $db->execute("function(x) { return x;}", array("input param"));
Here's how you could persist a function for later use (through the mongo shell)
db.system.js.save(
{ _id: "echoFunction",
value : function(x) { return x; }
}
)
Then later in PHP:
$response = $db->execute("echoFunction( 'test' )");
var_dump($response);
Edit2:
Your update function is much easier than I first understood. You simply need the following:
$db->update(
array("first_name" => "blah"),
array(
"$push" => array(
"scores" => array("score" => 16)
)
)
);
Edit2: Access your collection from inside a function
function push_score(id, score) {
//your logic here
//...
db.your_collection.update({_id: ObjectId(id), $push: {scores: {score: score}}})
}

Configure UniCastBus in NServiceBus using IWantToRunBeforeConfigurationIsFinalized

I would like to "hook in" and tweak configuration to UnicastBus and was looking at doing this using IWantToRunBeforeConfigurationIsFinalized.
I would like to tweak/set the value for: ForwardReceivedMessagesTo. Any ideas on how that should be done?
Unfortunately due to a bug (see https://github.com/Particular/NServiceBus/issues/1960), the only possible way is to programmatically replace the whole UnicastBusConfig, eg:
class Foo : IProvideConfiguration<UnicastBusConfig>
{
public UnicastBusConfig GetConfiguration()
{
var unicastBusConfig = new UnicastBusConfig
{
ForwardReceivedMessagesTo = "FooBar",
};
unicastBusConfig.MessageEndpointMappings = new MessageEndpointMappingCollection();
unicastBusConfig.MessageEndpointMappings.Add(...);
return unicastBusConfig;
}
}
But that is quite ugly :(

Full text search using linq

I have a list of names in a observable collection returned from wcf service and database is oracle, I want to make full text search on the list using LINQ.
service is consumed in silverlight application.
Any suggestions pls.
How about this?
var found = thelist.Where(str => str.Contains(strToSearchFor));
or maybe this -
var found = thelist.Where(str => str.ToLower().Contains(strToSearchFor.ToLower()));
if it is not list of strings it would like like this:
var found = thelist.Where(obj => obj.strProperty.Contains(strToSearchFor));
If you need this solution to be case insensitive the solution of Hogan can be done without creatring a new string (by using the ToLower() method).
First, create an extension method:
public static class Extensions
{
public static bool Contains(this string source, string stringToMatch, StringComparison comparisonType)
{
return source.IndexOf(stringToMatch, comparisonType) >= 0;
}
}
Then you can make the Hogan solution case insensitive like this:
var found = thelist.Where(str => str.Contains(strToSearchFor, StringComparison.OrdinalIgnoreCase));

How to do case sensitive queries on dynamic fields

I want to do case sensitive queries against dynamic fields in a RavenDB index. I have seen that this can be done using an AbstractAnalyzerGenerator thing, but I have not found information on how to use it.
My document class looks similar to:
class Thing {
public string Name;
public DateTime CreatedAt;
public Dictionary<string, object> Properties;
}
The index map is set up like this:
Map = things => from thing in things
select new { Name = thing.Name,
CreatedAt = thing.CreatedAt,
_ = thing.Properties.Select( p =>
p.CreateField(p.Key, p.Value, false, true) );
}
Now I would like to use this magic AbstractAnalzyzerGenerator thing to make some of the property fields case sensitive, based on their name. Unfortunately I don't know how.. :)
ErikR,
If you need case sensitive, you need to do it like this:
p.CreateField(p.Key, p.Value, false, **false**) );