Not able to get TermVector results properly in SolrNet - solrnet

I'm not able to get TermVector results properly thru SolrNet. I tried with the following code.
QueryOptions options = new QueryOptions()
{
OrderBy = new[] { new SortOrder("markupId", Order.ASC) },
TermVector = new TermVectorParameters
{
Fields = new[] { "text" },
Options = TermVectorParameterOptions.All
}
};
var results = SolrMarkupCore.Query(query, options);
foreach (var docVectorResult in results.TermVectorResults)
{
foreach (var vectorResult in docVectorResult.TermVector)
System.Diagnostics.Debug.Print(vectorResult.ToString());
}
In the above code, results.TermVectorResults in the outer foreach gives the proper count whereas docVectorResult.TermVector in the inner foreach is empty.
I've copied the generated solr query of the above code and issued against solr admin and I'm properly getting the termVectors values. The actual query I issued is below
http://localhost:8983/solr/select/?sort=markupId+asc&tv.tf=true&start=0&q=markupId:%2823%29&tv.offsets=true&tv=true&tv.positions=true&tv.fl=text&version=2.2&rows=50

First you should check HTTP query to sure termvector feature is set property.
If it's not OK, change your indexing based on:
The Term Vector Component
If it is OK,You can use "ExtraParams" by changing the handler to termvector handler. Try this:
public SolrQueryExecuter<Product> instance { get; private set; }
public ICollection<TermVectorDocumentResult> resultDoc(string q)
{
string SERVER="http://localhost:7080/solr/core";//change this
var container = ServiceLocator.Current as SolrNet.Utils.Container;
instance = new SolrQueryExecuter<Product>(
container.GetInstance<ISolrAbstractResponseParser<Product>>(),
new SolrConnection(SERVER),
container.GetInstance<ISolrQuerySerializer>(),
container.GetInstance<ISolrFacetQuerySerializer>(),
container.GetInstance<ISolrMoreLikeThisHandlerQueryResultsParser<Product>>());
instance.DefaultHandler = "/tvrh";
SolrQueryResults<Product> results =
instance.Execute(new SolrQuery(q),
new QueryOptions
{
Fields = new[] { "*" },
Start = 0,
Rows = 10,
ExtraParams = new Dictionary<string, string> {
{ "tv.tf", "false" },
{ "tv.df", "false" },
{ "tv.positions", "true" },
{ "tv", "true" },
{ "tv.offsets", "false" },
{ "tv.payloads", "true" },
{ "tv.fl", "message" },// change the field name here
}
}
);
return results.TermVectorResults;
}

Related

Elasticsearch - NEST - Upsert

I have the following two classes
Entry
public class Entry
{
public Guid Id { get; set; }
public IEnumerable<Data> Data { get; set; }
}
EntryData
public class EntryData
{
public string Type { get; set; }
public object Data { get; set; }
}
I have a bunch of different applications that produces messages to a queue that I then consume in a separate application to store that data in elasticsearch.
Im using a CorrelationId for all the messages and I want to use this ID as the ID in elasticsearch.
So given the following data:
var id = Guid.Parse("1befd5b62b944b4aa600c85632159e11");
var entries = new List<Entry>
{
new Entry
{
Id = id,
Data = new List<EntryData>
{
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION1_Received"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION1_Validated"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION1_Published"
},
}
},
new Entry
{
Id = id,
Data = new List<EntryData>
{
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION2_Received"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION2_Validated"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION2_Published"
},
}
},
new Entry
{
Id = id,
Data = new List<EntryData>
{
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION3_Received"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION3_Validated"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION3_Published"
},
}
},
};
I want this to be saved as one entry in elasticsearch where ID == 1befd5b6-2b94-4b4a-a600-c85632159e11 and a data array that contains 9 elements.
Im struggling a bit with getting this to work, when trying the following:
var result = await _elasticClient.BulkAsync(x => x.Index("journal").UpdateMany(entries, (descriptor, entry) => {
descriptor.Doc(entry);
return descriptor.Upsert(entry);
}), cancellationToken);
But this is just overwriting whatever already exists in the data array and the count is 3 instead of 9 (only the Application3 entries are saved).
So, is it possible to do what I want to do? I never worked with elasticsearch before so it feels like maybe Im missing something simple here... :)
Managed to solve it like this:
var result = await _elasticClient.BulkAsync(x => x.Index("journal").UpdateMany(entries, (descriptor, entry) => {
var script = new InlineScript("ctx._source.data.addAll(params.data)")
{
Params = new Dictionary<string, object> {{"data", entry.Data}}
};
descriptor.Script(b => script);
return descriptor.Upsert(entry);
}), cancellationToken);

Is an nGram fuzzy search possible?

I'm trying to get an nGram filter to work with a fuzzy search, but it won't. Specifically, I'm trying to get "rugh" to match on "rough".
I don't know whether it's just not possible, or it is possible but I've defined the mapping wrong, or the mapping is fine but my search isn't defined correctly.
Mapping:
{
settings = new
{
index = new
{
number_of_shards = 1,
number_of_replicas = 1,
analysis = new
{
filter = new
{
edge_ngram_filter = new
{
type = "nGram",
min_gram = 3,
max_gram = 8
}
}, // filter
analyzer = new
{
analyzer_ngram = new
{
type = "custom",
tokenizer = "standard",
filter = new string[]
{
"lowercase",
"edge_ngram_filter"
}
}
} // analyzer
} // analysis
} // index
}, // settings
mappings = new
{
j_cv = new
{
properties = new
{
Text = new
{
type = "text",
include_in_all = false,
analyzer = "analyzer_ngram",
search_analyzer = "standard"
}
}
} // j_cv
} // mappings
}
Document:
{
Id = Guid.NewGuid(),
Name = "Jimmy Riddle",
Keyword = new List<string>(new string[] { "Hunting", "High", "Hotel", "California" }),
Text = "Rough Justice was a program on BBC some years ago. It was quite interesting. Will this match?"
}
Search:
{
query = new
{
query_string = new
{
fields = new string[] { "Text" },
fuzziness = "3",
query = "rugh"
}
}
}
Incidentally, "ugh" does match which is what you'd expect.
Thanks for any help you can give,
Adam.
The same analyzer should usually be applied at index and search time, so search_analyzer=standard is wrong, it should be working if you remove it.
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-analyzer.html
Edit:
You forgot the fuzzy operator "~" in your query, if you add it to "rugh" it will work!

Low level Elastic search not working properly

I am trying to do Elastic search with sort option. My query is like this:
var client = new ElasticClient(settings);
var query = new
{
query = new
{
term = new { title = "7-0 v Spurs" }
},
Sort = new List<ISort>
{
new SortField { Field = "releaseFrom", Order = SortOrder.Descending }
}
};
and my search is like this:
var stream = new MemoryStream();
client.Serializer.Serialize(query, stream);
var jsonQuery = System.Text.Encoding.UTF8.GetString(stream.ToArray());
var qRequest = new SearchRequest(jsonQuery);
var searchResponse = client.LowLevel.Search<SearchResponse<dynamic>>(IndexingService.IndexName, "article_en", qRequest);
I am getting the result, but it returns records which does not match the title and also it does not sort.
This is the query which is generated:
{ "query": { "term": { "title": "7-0 v Spurs" } }, "sort": [ { "releaseFrom": { "order": "desc" } } ] }
Anybody, with suggestion if I miss something here.
Found the solution.
Used ElasticLowLevelClient instead of ElasticClient.
Code is like this:
var lowlevelClient = new ElasticLowLevelClient(settings);
var stream = new MemoryStream();
lowlevelClient.Serializer.Serialize(query, stream);
var jsonQuery = System.Text.Encoding.UTF8.GetString(stream.ToArray());
var searchResponse = lowlevelClient.Search< SearchResponse<dynamic>>(IndexingService.IndexName, "article_en", jsonQuery);
one change in query also
match = new { title = "7-0 v Spurs" }

ElasticSearch - NEST equivalent for the "nested Filter Query" in Sense?

I am new to Elastic search,
I have object structure like,
class Student
{
int schoolId;
List<Subject> Subjects;
}
class Subject
{
string title;
string type;
}
I am trying to list down all the unique Subject titles. So far, I have the following Query that works in Sense and gives me desired result.
curl -XGET "http://localhost:9200/school-v0.1/student/_search?search_type=count&routing=5" -d '{
"filter":
{
"term": { "schoolId": 5 }
},
"aggs":
{
"SubjectsAggr":
{
"nested": { "path": "Subjects" },
"aggs":
{
"TitlesAggr":
{
"terms": { "field": "subject.title" }
}
}
}
}
}'
But I am not getting the NEST equivalent of the same. Refer below.
Am I missing something?
var result = this.ElasticClient.Search<Student>(q => q
.Index(this.ElasticClient.Index)
.Routing(schoolId)
.SearchType(SearchType.Count)
.Filter(q1 => q1.Term(a => a.schoolId, schoolId))
.Aggregations(student => student.Nested("SubjectsAggr", b => b.Path("subjects")
.Aggregations(sub => sub.Terms("TitlesAggr", s => s.Field("subject.title"))))));
//Below is what I hope to do, but the I get compilation errors because there seems to be something wrong with above NEST query that I have written
var subjectsAggregation = esResult.Aggs.Nested("SubjectsAggr");
var titlesAggregation = subjectsAggregation.Aggs.Terms("TitlesAggr");
var subjects = new List<string>();
foreach (var s in titlesAggregation.Items)
{
subjects.Add(s.Key);
}
Could you please help me find it? Thank you.
My NEST query was indeed correct. I was only not fetching the results out in appropriate way. I am now able to extract the needed information out of the search result as shown below.
var subjectsAggregation = result.Aggs.Nested("SubjectsAggr");
var titlesAggregation = subjectsAggregation.Aggregations["TitlesAggr"];
var titlesBucket = titlesAggregation as Bucket;
var titles = new List<string>();
if (titlesBucket != null)
{
foreach (var title in titlesBucket.Items)
{
titles.Add((((KeyItem) title).Key));
}
}

ElasticSearch NEST library to retrieve certain fields

Trying to achieve following,
Retrieve articles that match given id and genre
Retrieve selected fields for matching records
I have tried this with Sense(chrome plugin),
POST /d3acampaign/article/_search
{
"fields": ["title","genre"] ,
"query": {
"filtered": {
"filter": {
"bool": {
"must": [{
"term": {
"id": "6"
}
},
{
"term": {
"genre": "metal"
}
}]
}
}
}
}
}
For C# code i am trying to build the query using following construct,
FilterContainer fc = null;
TermFilter title = new TermFilter()
{
Field = "id",
Value = "6",
};
TermFilter genre = new TermFilter()
{
Field = "genre",
Value = "metal",
};
fc = title & genre;
QueryContainer qc = new FilteredQuery() { Filter = fc };
var searchRequest = new SearchRequest
{
SearchType = Elasticsearch.Net.SearchType.QueryAndFetch,
Query = qc,
Indices = new IndexNameMarker[] {"journal"},
Types = new TypeNameMarker[] { "article" },
};
var r = client.SearchAsync<Article>(searchRequest);
var l = (List<Article>) r.Result.Documents;
I am able to run this query and get matching records, but i amnt sure how to specify selected fields to retrieve. Let me know what can be changed in C# code to specify necessary fields.
Thanks in advance.
Based on this answer you can modify your request object as follow:
var searchRequest = new SearchRequest
{
...
Fields = new List<PropertyPathMarker>
{
Property.Path<Article>(p => p.YourField)
}
};
or if you will decide to use source filtering:
var searchRequest = new SearchRequest
{
...
Source = new SourceFilter
{
Include = new []
{
Property.Path<Article>(p => p.YourField)
}
}
};
Hope it helps.

Resources