# Querying Relationships

When querying an entity, you may want to restrict the query based on the existence or absence of a related entity.  You can do that using the following four methods:

## has

| Name             | Type    | Required | Default | Description                                                                           |
| ---------------- | ------- | -------- | ------- | ------------------------------------------------------------------------------------- |
| relationshipName | String  | `true`   |         | The relationship to check.  Can also be a dot-delimited list of nested relationships. |
| operator         | String  | `false`  |         | An optional operator to constrain the check. See qb for a list of valid operators.    |
| count            | numeric | `false`  |         | An optional count to constrain the check.                                             |
| negate           | boolean | `false`  | `false` | If true, checks for the the absence of the relationship instead of its existence.     |

Checks for the existence of a relationship when executing the query.

By default, a `has` constraint will only return entities that have one or more of the related entity.

```javascript
getInstance( "User" ).has( "posts" ).get();
```

An optional operator and count can be added to the call.

```javascript
getInstance( "User" ).has( "posts", ">", 2 ).get();
```

Nested relationships can be checked by passing a dot-delimited string of relationships.

```javascript
getInstance( "User" ).has( "posts.comments" ).get();
```

## doesntHave

| Name             | Type    | Required | Default | Description                                                                           |
| ---------------- | ------- | -------- | ------- | ------------------------------------------------------------------------------------- |
| relationshipName | String  | `true`   |         | The relationship to check.  Can also be a dot-delimited list of nested relationships. |
| operator         | String  | `false`  |         | An optional operator to constrain the check. See qb for a list of valid operators.    |
| count            | numeric | `false`  |         | An optional count to constrain the check.                                             |

Checks for the absence of a relationship when executing the query.

By default, a `doesntHave` constraint will only return entities that have zero of the related entity.

```javascript
getInstance( "User" ).doesntHave( "posts" ).get();
```

An optional operator and count can be added to the call.

```javascript
getInstance( "User" ).doesntHave( "posts", "<=", 1 ).get();
```

Nested relationships can be checked by passing a dot-delimited string of relationships.

```javascript
getInstance( "User" ).doesntHave( "posts.comments" ).get();
```

## whereHas

| Name             | Type     | Required | Default | Description                                                                           |
| ---------------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------- |
| relationshipName | String   | `true`   |         | The relationship to check.  Can also be a dot-delimited list of nested relationships. |
| closure          | Function | `true`   |         | A closure to constrain the relationship check.                                        |
| operator         | String   | `false`  |         | An optional operator to constrain the check. See qb for a list of valid operators.    |
| count            | numeric  | `false`  |         | An optional count to constrain the check.                                             |
| negate           | boolean  | `false`  | `false` | If true, checks for the the absence of the relationship instead of its existence.     |

When you need to have more control over the relationship constraint, you can use `whereHas`.  This method operates similarly to `has` but also accepts a callback to configure the relationship constraint.

The `whereHas` callback is passed a builder instance configured according to the relationship.  You may call any entity or query builder methods on it as usual.

```javascript
getInstance( "User" )
    .whereHas( "posts", function( q ) {
	      q.where( "body", "like", "%different%" );
    } )
		.get();
```

When you specify a nested relationship, the builder instance is configured for the last relationship specified.

```javascript
getInstance( "User" )
    .whereHas( "posts.comments", function( q ) {
	      q.where( "body", "like", "%great%" );
	  } )
	  .get();
```

An optional operator and count can be added to the call, as well.

```javascript
getInstance( "User" )
    .whereHas( "posts.comments", function( q ) {
	      q.where( "body", "like", "%great%" );
	  }, ">", 2 )
	  .get();
```

## whereDoesntHave

| Name             | Type     | Required | Default | Description                                                                           |
| ---------------- | -------- | -------- | ------- | ------------------------------------------------------------------------------------- |
| relationshipName | String   | `true`   |         | The relationship to check.  Can also be a dot-delimited list of nested relationships. |
| closure          | Function | `true`   |         | A closure to constrain the relationship check.                                        |
| operator         | String   | `false`  |         | An optional operator to constrain the check. See qb for a list of valid operators.    |
| count            | numeric  | `false`  |         | An optional count to constrain the check.                                             |

The `whereDoesntHave` callback is passed a builder instance configured according to the relationship.  You may call any entity or query builder methods on it as usual.

```javascript
getInstance( "User" )
    .whereDoesntHave( "posts", function( q ) {
	      q.where( "body", "like", "%different%" );
    } )
		.get();
```

When you specify a nested relationship, the builder instance is configured for the last relationship specified.

```javascript
getInstance( "User" )
    .whereDoesntHave( "posts.comments", function( q ) {
	      q.where( "body", "like", "%great%" );
	  } )
	  .get();
```

An optional operator and count can be added to the call, as well.

```javascript
getInstance( "User" )
    .whereDoesntHave( "posts.comments", function( q ) {
	      q.where( "body", "like", "%great%" );
	  }, ">", 2 )
	  .get();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://quick.ortusbooks.com/3.0.0/guide-1/relationships/querying-relationships.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
