Reputation: 11543
Lets say i have an index that contains documents that represent a Message in a discussion.
that document owns a discussionId property.
(it also has its own ID "that represent MessageId")
now, i need to find all discussionIds that have no documents (messages) that match a query.
for example:
"Find all discussionIds , that have no message that contains the text 'YO YO'"
how can i do that?
the class is similar to this:
public class Message
{
public string Id{get;set}
public string DiscussionId {get;set}
public string Text{get;set}
}
Upvotes: 0
Views: 56
Reputation: 125538
You just need to wrap the query that would find matches for the phrase "YO YO" in a bool
query must_not
clause.
With NEST
client.Search<Message>(s => s
.Query(q => q
.Bool(b => b
.MustNot(mn => mn
.MatchPhrase(m => m
.Field(f => f.Text)
.Query("YO YO")
)
)
)
)
);
which, with operator overloading, can be shortened to
client.Search<Message>(s => s
.Query(q => !q
.MatchPhrase(m => m
.Field(f => f.Text)
.Query("YO YO")
)
)
);
Both produce the query
{
"query": {
"bool": {
"must_not": [
{
"match": {
"text": {
"type": "phrase",
"query": "YO YO"
}
}
}
]
}
}
}
To only return DiscussionId
values, you can use source filtering
client.Search<Message>(s => s
.Source(sf => sf
.Includes(f => f
.Field(ff => ff.DiscussionId)
)
)
.Query(q => !q
.MatchPhrase(m => m
.Field(f => f.Text)
.Query("YO YO")
)
)
);
And, if you want to get them all, you can use the scroll API
var searchResponse = client.Search<Message>(s => s
.Scroll("1m")
.Source(sf => sf
.Includes(f => f
.Field(ff => ff.DiscussionId)
)
)
.Query(q => !q
.MatchPhrase(m => m
.Field(f => f.Text)
.Query("YO YO")
)
)
);
// fetch the next batch of documents, using the scroll id returned from
// the previous call. Do this in a loop until no more docs are returned.
searchResponse = client.Scroll<Message>("1m", searchResponse.ScrollId);
Upvotes: 1