Search C# NEST query on attachments


(Alina Frey) #1
  • My goal is to be able to perform a search on the Content of a list of documents called PersonDocuments attached to IndexablePersonModel, and return the persons that have documents that contain the query term.

  • The query that I'm using is returning the respective persons ONLY IF the query term matches EXACTLY the WHOLE content of the attached document. But if I search only for one word in the document, nothing is returned. Please advise.

  • Using ingest-attachment plugin.

  • Elasticsearch version: 5.5.1

  • NEST: 5.5

  • PersonDocuments is a list of IndexablePersonDocument on the IndexablePersonModel

public IEnumerable<IndexablePersonDocument> PersonDocuments { get; set; }
  • And one of the attributes of IndexablePersonDocument is string Content.

  • Here is the query that I have so far:

protected override QueryContainer Query(QueryContainerDescriptor<IndexablePersonModel> q)
{
	var returnQuery = q
	.Match(m => m
		.Field(p => p.Name.Suffix(SearchConstants.Keyword))
		.Boost(SearchConstants.Boosts.XXLarge)
		.Query(Form.Query)
	)
	|| q.Nested(n => n
		.Boost(SearchConstants.Boosts.XXXLarge)
		.InnerHits(i => i.Explain())
		.Path(p => p.PersonDocuments)
		.Query(nq => +nq
			.Bool(b => b
				.Should(
					s => s.Term(p => p.PersonDocuments.First().Attachment.Content.Suffix(SearchConstants.Keyword), Form.Query)
				).MinimumShouldMatch(MinimumShouldMatch.Fixed(1))
			)
		)
		.IgnoreUnmapped()
	)
	|| q.FunctionScore(fs => fs
		.MaxBoost(SearchConstants.Boosts.Large)
		.Functions(ff => ff
			.FieldValueFactor(fvf => fvf
				.Field(p => p.TotalPurchasedQuantity)
				.Factor(0.0001)
			)
		)
		.Query(query => query
			.MultiMatch(m => m
				.Fields(f => f
						.Field(p => p.Name, SearchConstants.Boosts.XSmall)
						.Field(p => p.PersonDocuments.First().Attachment.Content, SearchConstants.Boosts.XXLarge)
				)
				.Operator(Operator.And)
				.Query(Form.Query)
			)
		)
	)
	#endregion
	;

	return returnQuery;
}  

(Russ Cam) #2

How is this property mapped as a field in Elasticsearch? Would you be able to show the JSON mapping in the target index? I see that the PersonDocuments property is used in both a nested query and a multi_match query, so one of these queries won't be working as expected, depending on how it's mapped.


(Alina Frey) #3

I figured it out. I was supposed to use a Match:

q.Nested(n => n
	.Boost(SearchConstants.Boosts.XXXLarge)
	.ScoreMode(NestedScoreMode.Max) // Give the person the _score from the best-matching nested document
	.InnerHits(i => i.Explain(true))
	.Path(p => p.PersonDocuments)
	.Query(nq => +nq
		.Match(m => m
			.Field( a => a.PersonDocuments.First().Attachment.Content)
			.Query(Form.Query)
		)
	)
	.IgnoreUnmapped()
)

(Russ Cam) #4

There is the usage of a property on PersonDocuments inside the query of the function_score query.

If PersonDocuments is mapped as a nested type, this should be inside of a nested query here too, and combined with the match queryonName`.