Reputation: 888
I would like to do a Facet Search that returns the "$$SEARCH_META" based on the documentation (https://www.mongodb.com/docs/atlas/atlas-search/facet/). A snippet of the search definition from the documentation is like the below. Im interested in defining the "{"$replaceWith": "$$SEARCH_META"}"
{
"$facet": {
"docs": [
{ "$project":
{
"title": 1,
"released": 1
}
}
],
"meta": [
{"$replaceWith": "$$SEARCH_META"},
{"$limit": 1}
]
}
},
I have the following book Collection (Reduced for brevity)
[
{
"_id": "11111",
"Published": true,
"Description": "Description fo title 1",
"Publisher": "BigBook Pub",
"Title": "This is my first BigBook title",
"Type": "fiction"
}
]
My code (which ill show shortly) generates the following aggregation definition ($search, $project and $facet)
[
{
"$search": {
"facet": {
"operator": {
"compound": {
"should": [
{
"text": {
"query": "Jon West",
"path": [
"Title",
"Publisher",
"Description"
]
}
}
]
}
},
"facets": {
"publisherFacet": {
"type": "string",
"path": "Publisher"
},
"typeFacet": {
"type": "string",
"path": "Type"
}
}
},
"index": "my-index"
}
},
{
"$project": {
"_id": 1,
"Publisher": 1,
"Title": 1,
"Description": 1
}
},
{
"$facet": {
"docs": [
{
"$project": {
"_id": 1,
"Publisher": 1,
"Title": 1,
"Description": 1
}
}
]
}
}
]
From the above you can see that it is generating the $facet aggregation ($facet/docs/$project) which is similar to the definition in the atlas documentation, but im unable to work out how to generate section "$facet/meta/$replaceWith" as in the documentation
The Code that produced the above aggregation definition is as follows. It was simplfied for brevity. You will see a commented out bit where i was trying to generate the "{"$replaceWith": "$$SEARCH_META"}" but without successful. How do i generate this section?
public IEnumerable<Book> Search<T>(IMongoCollection<Book> collection)
{
var aggregateStage = collection.Aggregate();
#region $search Aggregation Stage
var compoundSearchDefinition = Builders<Book>.Search.Compound();
compoundSearchDefinition.Should(Builders<Book>.Search.Text(listOfSearchableFields, 'Jon West'));
var myFacets = new List<SearchFacet<Book>>
{
Builders<Book>.SearchFacet.String("publisherFacet", "Publisher"),
Builders<Book>.SearchFacet.String("typeFacet", "Type")
};
var searchAndFacetDefinition = Builders<Book>.Search.Facet(compoundSearchDefinition, facets: myFacets);
var textSearchResult = aggregateStage.Search(
searchAndFacetDefinition,
indexName: searchIndexSettings.Value.BookIndexName);
var projectionDefinition = new ProjectionDefinitionBuilder<Book>()
.Include(clip => clip.Id)
.Include(clip => clip.Publisher)
.Include(clip => clip.Title)
.Include(clip => clip.Description);
var searchAggregateStage = textSearchResult.Project<Book>(projectionDefinition);
#endregion
#region $facet Aggregation Stage
PipelineDefinition<Book, Book> projectPipelineDef = new EmptyPipelineDefinition<Book>();
PipelineDefinition<Book, Book> metaPipelineDef = new EmptyPipelineDefinition<Book>();
ProjectionDefinition<Book, Book> projection1 = Builders<Book>.Projection
.Include(clip => clip.Id)
.Include(clip => clip.Publisher)
.Include(clip => clip.Title)
.Include(clip => clip.Description);
var projDef = projectPipelineDef.Project(projection1);
// var metaDef = metaPipelineDef.ReplaceWith("$$SEARCH_META");
var aggregateFacet1 = AggregateFacet.Create("docs", projDef);
//var aggregateFacet2 = AggregateFacet.Create("meta", metaDef);
var aggregateFacetList = new List<AggregateFacet<Book>>()
{
aggregateFacet1,
// aggregateFacet2
};
var facetAggregateFluent = searchAggregateStage.Facet(aggregateFacetList);
#endregion
var result1 = facetAggregateFluent.ToList()[0].Facets[0].Output<Book>();
return result1;
}
And the Book Class
public class Book
{
public bool Published { get; set; }
public string Description { get; set; }
public string Publisher { get; set; }
public string Title { get; set; }
public string Type { get; set; }
}
Upvotes: 0
Views: 189
Reputation: 888
I manage to get it working by doing the following
So instead of
// var metaDef = metaPipelineDef.ReplaceWith("$$SEARCH_META");
I did this
var searchMetaPipelineDefinition = new EmptyPipelineDefinition<Book>()
.AppendStage<Book, Book, Book>("{\"$replaceWith\":\"$$SEARCH_META\"}")
.AppendStage<Book, Book, Metum>("{\"$limit\":1}");
With these additional classes to represent the Facet and metadata
public class Bucket
{
public string _id { get; set; }
public long count { get; set; }
}
public class TypeFacet
{
public List<Bucket> buckets { get; set; }
}
public class Count
{
public long lowerBound { get; set; }
}
public class Facet
{
public TypeFacet clipTypeFacet { get; set; }
public PublisherFacet publisherFacet { get; set; }
}
public class Metum
{
public Count count { get; set; }
public Facet facet { get; set; }
}
public class PublisherFacet
{
public List<Bucket> buckets { get; set; }
}
Upvotes: 0